c++ string unicode c++-faq wstring

c++ - std:: wstring VS std:: string



unicode c++-faq (12)

No puedo entender las diferencias entre std::string y std::wstring . Sé que wstring admite caracteres anchos como los caracteres Unicode. Tengo las siguientes preguntas:

  1. ¿Cuándo debo usar std::wstring sobre std::string ?
  2. ¿Puede std::string contener todo el conjunto de caracteres ASCII, incluidos los caracteres especiales?
  3. ¿Es std::wstring soportado por todos los compiladores de C ++ populares?
  4. ¿Qué es exactamente un " personaje ancho "?

string ? wstring ?

std::string es una std::string basic_string una plantilla en un char , y std::wstring en un wchar_t .

char vs. wchar_t

se supone que char tiene un carácter, generalmente un carácter de 8 bits.
Se supone que wchar_t tiene un carácter ancho, y luego, las cosas se ponen difíciles:
En Linux, un wchar_t es de 4 bytes, mientras que en Windows, es de 2 bytes.

¿Qué hay de Unicode , entonces?

El problema es que ni char ni wchar_t están directamente vinculados a unicode.

En linux?

Tomemos un sistema operativo Linux: Mi sistema Ubuntu ya es unicode. Cuando trabajo con una cadena de caracteres, está codificada de forma nativa en UTF-8 (es decir, una cadena de caracteres Unicode). El siguiente código:

#include <cstring> #include <iostream> int main(int argc, char* argv[]) { const char text[] = "olé" ; std::cout << "sizeof(char) : " << sizeof(char) << std::endl ; std::cout << "text : " << text << std::endl ; std::cout << "sizeof(text) : " << sizeof(text) << std::endl ; std::cout << "strlen(text) : " << strlen(text) << std::endl ; std::cout << "text(ordinals) :" ; for(size_t i = 0, iMax = strlen(text); i < iMax; ++i) { std::cout << " " << static_cast<unsigned int>( static_cast<unsigned char>(text[i]) ); } std::cout << std::endl << std::endl ; // - - - const wchar_t wtext[] = L"olé" ; std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ; //std::cout << "wtext : " << wtext << std::endl ; <- error std::cout << "wtext : UNABLE TO CONVERT NATIVELY." << std::endl ; std::wcout << L"wtext : " << wtext << std::endl; std::cout << "sizeof(wtext) : " << sizeof(wtext) << std::endl ; std::cout << "wcslen(wtext) : " << wcslen(wtext) << std::endl ; std::cout << "wtext(ordinals) :" ; for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i) { std::cout << " " << static_cast<unsigned int>( static_cast<unsigned short>(wtext[i]) ); } std::cout << std::endl << std::endl ; return 0; }

saca el siguiente texto:

sizeof(char) : 1 text : olé sizeof(text) : 5 strlen(text) : 4 text(ordinals) : 111 108 195 169 sizeof(wchar_t) : 4 wtext : UNABLE TO CONVERT NATIVELY. wtext : ol� sizeof(wtext) : 16 wcslen(wtext) : 3 wtext(ordinals) : 111 108 233

Verás que el texto "olé" en char está realmente construido por cuatro caracteres: 110, 108, 195 y 169 (sin contar el cero final). (Te dejaré estudiar el código wchar_t como un ejercicio)

Por lo tanto, cuando trabaje con un char en Linux, normalmente debería terminar usando Unicode sin siquiera saberlo. Y como std::string funciona con char , entonces std::string ya está listo para Unicode.

Tenga en cuenta que std::string , al igual que la API de la cadena C, considerará que la cadena "olé" tiene 4 caracteres, no tres. Por lo tanto, debe tener cuidado al truncar / jugar con caracteres Unicode, ya que en UTF-8 está prohibida alguna combinación de caracteres.

En Windows?

En Windows, esto es un poco diferente. Win32 tenía que admitir una gran cantidad de aplicaciones que trabajaban con char y en diferentes charsets / codepages producidas en todo el mundo, antes de la llegada de Unicode.

Por lo tanto, su solución fue interesante: si una aplicación funciona con char , las cadenas de caracteres se codifican / imprimen / muestran en las etiquetas de la GUI utilizando la página de códigos / caracteres local de la máquina. Por ejemplo, "olé" sería "olé" en una Windows localizada en francés, pero sería algo diferente en una Windows localizada en cirílico ("olé" si usa Windows-1251 ). Por lo tanto, las "aplicaciones históricas" por lo general funcionarán igual que antes.

Para aplicaciones basadas en Unicode, Windows usa wchar_t , que tiene un ancho de 2 bytes, y está codificado en UTF-16 , que está codificado en Unicode en caracteres de 2 bytes (o por lo menos, el UCS-2 en su mayoría compatible, que es casi Lo mismo IIRC).

Las aplicaciones que usan char se dicen "multibyte" (porque cada glifo se compone de uno o más char s), mientras que las aplicaciones que usan wchar_t se dicen "widechar" (porque cada glifo se compone de uno o dos wchar_t . Ver MultiByteToWideChar y WideCharToMultiByte conversión Win32 API para más información.

Por lo tanto, si trabaja en Windows, deseará usar wchar_t (a menos que use un marco que lo wchar_t , como GTK+ o QT ...). El hecho es que detrás de escena, Windows trabaja con cadenas wchar_t , por lo que incluso las aplicaciones históricas tendrán sus cadenas de caracteres convertidas en wchar_t cuando usen API como SetWindowText() (función de API de bajo nivel para establecer la etiqueta en una GUI de Win32).

Problemas de memoria?

UTF-32 es de 4 bytes por carácter, por lo que no hay mucho que agregar, aunque solo sea que un texto UTF-8 y un texto UTF-16 siempre usarán menos o la misma cantidad de memoria que un texto UTF-32 (y generalmente menos ).

Si hay un problema de memoria, debe saber que para la mayoría de los idiomas occidentales, el texto UTF-8 utilizará menos memoria que el mismo UTF-16.

Aún así, para otros idiomas (chino, japonés, etc.), la memoria utilizada será la misma, o un poco más grande para UTF-8 que para UTF-16.

En general, UTF-16 usará principalmente 2 y ocasionalmente 4 bytes por caracteres (a menos que esté tratando con algún tipo de glifos de lenguaje esotérico (Klingon? Elvish?), Mientras que UTF-8 gastará de 1 a 4 bytes.

Consulte http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16 para obtener más información.

Conclusión

  1. ¿Cuándo debo usar std :: wstring sobre std :: string?

    En linux? Casi nunca (§).
    En Windows? Casi siempre (§).
    ¿En código multiplataforma? Depende de su caja de herramientas ...

    (§): a menos que use un conjunto de herramientas / marco que indique lo contrario

  2. ¿Puede std::string contener todo el conjunto de caracteres ASCII, incluidos los caracteres especiales?

    Aviso: Un std::string es adecuado para mantener un búfer ''binario'', donde un std::wstring no lo es.

    En linux? Sí.
    En Windows? Solo caracteres especiales disponibles para la configuración regional actual del usuario de Windows.

    Editar (Después de un comentario de Johann Gerell ):
    una std::string será suficiente para manejar todas las cadenas basadas en caracteres (cada char es un número de 0 a 255). Pero:

    1. Se supone que ASCII va de 0 a 127. Los caracteres más altos NO son ASCII.
    2. una char de 0 a 127 se mantendrá correctamente
    3. un char de 128 a 255 tendrá un significado dependiendo de su codificación (Unicode, Non-Unicode, etc.), pero podrá contener todos los glifos de Unicode siempre que estén codificados en UTF-8.
  3. ¿Es std::wstring soportado por casi todos los compiladores de C ++ populares?

    Sobre todo, con la excepción de los compiladores basados ​​en GCC que se portan a Windows.
    Funciona en mi g ++ 4.3.2 (bajo Linux), y usé la API de Unicode en Win32 desde Visual C ++ 6.

  4. ¿Qué es exactamente un personaje ancho?

    En C / C ++, es un tipo de carácter escrito wchar_t que es más grande que el tipo de carácter de char simple. Se supone que se utiliza para colocar dentro de los caracteres cuyos índices (como los glifos de Unicode) son más grandes que 255 (o 127, dependiendo de ...).



  1. cuando desee utilizar cadenas Unicode y no solo ascii, es útil para la internacionalización
  2. si pero no juega bien con 0
  3. sin saber de ninguno que no
  4. carácter ancho es la forma específica del compilador de manejar la representación de longitud fija de un carácter Unicode, para MSVC es un carácter de 2 bytes, para gcc entiendo que es de 4 bytes. y un +1 para http://www.joelonsoftware.com/articles/Unicode.html

  1. Cuando quieras tener caracteres anchos almacenados en tu cadena. wide depende de la implementación. Visual C ++ por defecto es de 16 bits si recuerdo correctamente, mientras que los valores por defecto de GCC dependen del destino. Tiene 32 bits de largo aquí. Tenga en cuenta que wchar_t (tipo de carácter ancho) no tiene nada que ver con unicode. Simplemente se garantiza que puede almacenar todos los miembros del conjunto de caracteres más grande que la implementación soporta por sus entornos locales, y al menos tanto como char. Puede almacenar cadenas Unicode finas en std::string usando la codificación utf-8 también. Pero no entenderá el significado de los puntos de código Unicode. Por str.size() tanto, str.size() no le dará la cantidad de caracteres lógicos en su cadena, sino simplemente la cantidad de elementos char o wchar_t almacenados en esa cadena / cadena de caracteres. Por esa razón, la gente de envoltura de gtk / glib C ++ ha desarrollado una clase Glib::ustring que puede manejar utf-8.

    Si su wchar_t tiene 32 bits de longitud, entonces puede usar utf-32 como codificación Unicode, y puede almacenar y manejar cadenas de Unicode usando una codificación fija (la longitud de utf-32 es fija). Esto significa que la función s.size() de s.size() devolverá la cantidad correcta de elementos wchar_t y caracteres lógicos.

  2. Sí, char siempre tiene al menos 8 bits de longitud, lo que significa que puede almacenar todos los valores ASCII.
  3. Sí, todos los compiladores principales lo soportan.

1) Como lo mencionó Greg, wstring es útil para la internacionalización, es cuando lanzará su producto en otros idiomas además del inglés.

4) Comprueba esto para ver el carácter ancho wchar_t


Con frecuencia uso std :: string para contener caracteres utf-8 sin ningún problema. Recomiendo encarecidamente hacer esto al interactuar con las API que usan utf-8 como el tipo de cadena nativo también.

Por ejemplo, uso utf-8 cuando conecto mi código con el intérprete de Tcl.

La advertencia principal es la longitud de la cadena std ::, ya no es el número de caracteres en la cadena.


Hay algunas respuestas muy buenas aquí, pero creo que hay algunas cosas que puedo agregar con respecto a Windows / Visual Studio. Tis se basa en mi experiencia con VS2015. En Linux, básicamente la respuesta es usar std::string codificado en UTF-8 en todas partes. En Windows / VS se vuelve más complejo. Aquí es por qué. Windows espera que las cadenas almacenadas utilizando caracteres se codifiquen utilizando la página de códigos de la configuración regional. Este es casi siempre el conjunto de caracteres ASCII seguido de otros 128 caracteres especiales, dependiendo de su ubicación. Permítanme decirles que esto no solo cuando se usa la API de Windows, hay otros tres lugares principales en los que estas cadenas interactúan con el estándar C ++. Estos son literales de cadena, salida a std::cout usando << y pasando un nombre de archivo a std::fstream .

Estaré aquí al frente que soy un programador, no un especialista en idiomas. Aprecio que USC2 y UTF-16 no sean lo mismo, pero para mis propósitos son lo suficientemente cercanos como para ser intercambiables y los uso como tales aquí. No estoy realmente seguro de qué utiliza Windows, pero generalmente tampoco necesito saberlo. He expresado UCS2 en esta respuesta, lo siento de antemano si molesto a alguien con mi ignorancia de este asunto y me complace cambiarlo si me equivoco.

Literales de cuerda

Si ingresa literales de cadena que contienen solo caracteres que pueden ser representados por su página de códigos, VS los almacena en su archivo con 1 byte por codificación de caracteres basada en su página de códigos. Tenga en cuenta que si cambia su página de códigos o le da su origen a otro desarrollador utilizando una página de códigos diferente, entonces creo (pero no lo he probado) que el personaje terminará siendo diferente. Si ejecuta su código en una computadora usando una página de códigos diferente, entonces no estoy seguro si el carácter cambiará también.

Si ingresa una serie de literales que no pueden representarse en la página de códigos, VS le pedirá que guarde el archivo como Unicode. El archivo será codificado como UTF-8. Esto significa que todos los caracteres no ASCII (incluidos los que están en su página de códigos) estarán representados por 2 o más bytes. Esto significa que si le das tu fuente a otra persona, la fuente se verá igual. Sin embargo, antes de pasar la fuente al compilador, VS convierte el texto codificado en UTF-8 en texto codificado en la página de códigos y los caracteres que faltan en la página de códigos se reemplazan con ? .

La única forma de garantizar la representación correcta de un literal de cadena Unicode en VS es preceder al literal de cadena con una L que lo convierte en un literal de cadena ancha. En este caso, VS convertirá el texto codificado en UTF-8 del archivo a UCS2. Luego debe pasar este literal de cadena a un constructor std::wstring o necesita convertirlo a utf-8 y colocarlo en una std::string .O si lo desea, puede usar las funciones de la API de Windows para codificarlo usando su página de códigos para colocarlo en un std::string, pero entonces es posible que no haya usado un literal de cadena ancha.

std :: cout

Cuando se envía a la consola usando <<solo puede usar std::string, no, std::wstringy el texto debe codificarse usando la página de códigos de su localidad. Si tiene una, std::wstringentonces debe convertirla utilizando una de las funciones de la API de Windows y cualquier carácter que no esté en su página de códigos será reemplazado por ?(tal vez pueda cambiar el carácter, no lo recuerdo).

std :: fstream filenames

El sistema operativo Windows usa UCS2 / UTF-16 para sus nombres de archivo, por lo que, independientemente de su página de códigos, puede tener archivos con cualquier carácter Unicode. Pero esto significa que para acceder o crear archivos con caracteres que no están en su página de códigos debe usar std::wstring. No hay otra manera. Esta es una extensión específica de Microsoft, por std::fstreamlo que probablemente no se compile en otros sistemas. Si usa std :: string, solo puede utilizar nombres de archivos que solo incluyan caracteres en su página de códigos.

Sus opciones

Si solo estás trabajando en Linux, entonces probablemente no llegaste tan lejos. Simplemente use UTF-8 en std::stringtodas partes.

Si solo está trabajando en Windows, utilice UCS2 en std::wstringtodas partes. Algunos puristas pueden decir que usar UTF8 y luego convertir cuando sea necesario, pero ¿por qué molestarse con la molestia?

Si eres multiplataforma, entonces es un desastre ser franco. Si intenta usar UTF-8 en cualquier lugar de Windows, entonces debe tener mucho cuidado con sus cadenas de caracteres y la salida a la consola. Fácilmente puedes corromper tus cuerdas allí. Si utiliza std::wstringcualquier parte de Linux, es posible que no tenga acceso a la versión amplia de std::fstream, por lo que debe hacer la conversión, pero no existe riesgo de corrupción. Así que personalmente creo que esta es una mejor opción. Muchos no estarían de acuerdo, pero no estoy solo, es el camino que tomó wxWidgets, por ejemplo.

Otra opción podría ser typedef unicodestringcomo std::stringen Linux y std::wstringen Windows, y tener una macro llamada UNI () que prefija L en Windows y nada en Linux, luego el código

#include <fstream> #include <string> #include <iostream> #include <Windows.h> #ifdef _WIN32 typedef std::wstring unicodestring; #define UNI(text) L ## text std::string formatForConsole(const unicodestring &str) { std::string result; //Call WideCharToMultiByte to do the conversion return result; } #else typedef std::string unicodestring; #define UNI(text) text std::string formatForConsole(const unicodestring &str) { return str; } #endif int main() { unicodestring fileName(UNI("fileName")); std::ofstream fout; fout.open(fileName); std::cout << formatForConsole(fileName) << std::endl; return 0; }

Estaría bien en cualquier plataforma, creo.

Respuestas

Así que para responder a tus preguntas.

1) Si está programando para Windows, entonces todo el tiempo, si es multiplataforma, entonces quizás todo el tiempo, a menos que quiera lidiar con posibles problemas de corrupción en Windows o escriba algún código con una plataforma específica #ifdefspara solucionar las diferencias, si solo usa Linux entonces nunca.

2) si. Además, en Linux puede usarlo para todos los Unicode también. En Windows solo puede usarlo para todos los códigos Unicode si elige codificar manualmente usando UTF-8. Pero la API de Windows y las clases estándar de C ++ esperarán std::stringque se codifiquen utilizando la página de códigos de configuración regional. Esto incluye todos los ASCII más otros 128 caracteres que cambian dependiendo de la página de códigos que su computadora está configurada para usar.

3) Creo que sí, pero si no, entonces es solo un simple typedef de ''std :: basic_string'' usando en wchar_tlugar dechar

4) Un carácter ancho es un tipo de carácter que es más grande que el chartipo estándar de 1 byte . En Windows es de 2 bytes, en Linux es de 4 bytes.


Las aplicaciones que no están satisfechas con solo 256 caracteres diferentes tienen la opción de usar caracteres anchos (más de 8 bits) o una codificación de longitud variable (una codificación multibyte en la terminología de C ++) como UTF-8. Los caracteres anchos generalmente requieren más espacio que una codificación de longitud variable, pero son más rápidos de procesar. Las aplicaciones en varios idiomas que procesan grandes cantidades de texto usualmente usan caracteres anchos al procesar el texto, pero lo convierten a UTF-8 cuando lo almacenan en el disco.

La única diferencia entre una string y una wstring es el tipo de datos de los caracteres que almacenan. Una cadena almacena caracteres cuyo tamaño se garantiza en al menos 8 bits, por lo que puede usar cadenas para procesar, por ejemplo, texto ASCII, ISO-8859-15 o UTF-8. El estándar no dice nada sobre el conjunto de caracteres o la codificación.

Prácticamente todos los compiladores utilizan un conjunto de caracteres cuyos primeros 128 caracteres se corresponden con ASCII. Este es también el caso de los compiladores que utilizan la codificación UTF-8. Lo importante a tener en cuenta cuando se utilizan cadenas en UTF-8 o alguna otra codificación de longitud variable, es que los índices y las longitudes se miden en bytes, no en caracteres.

El tipo de datos de un wstring es wchar_t , cuyo tamaño no está definido en el estándar, excepto que tiene que ser al menos tan grande como un char, generalmente 16 bits o 32 bits. wstring se puede utilizar para procesar texto en la codificación de caracteres anchos definida por la implementación. Debido a que la codificación no está definida en el estándar, no es sencillo convertir entre cadenas y cadenas. Tampoco se puede asumir que las cadenas tengan una codificación de longitud fija.

Si no necesita soporte en varios idiomas, es posible que esté de acuerdo con usar solo cadenas regulares. Por otro lado, si está escribiendo una aplicación gráfica, a menudo ocurre que la API solo admite caracteres anchos. Entonces es probable que desee utilizar los mismos caracteres anchos al procesar el texto. Tenga en cuenta que UTF-16 es una codificación de longitud variable, lo que significa que no puede asumir length() para devolver el número de caracteres. Si la API utiliza una codificación de longitud fija, como UCS-2, el procesamiento se vuelve fácil. La conversión entre caracteres anchos y UTF-8 es difícil de hacer de manera portátil, pero, de nuevo, la API de la interfaz de usuario probablemente admita la conversión.


Por lo tanto, cada lector aquí ahora debe tener una comprensión clara sobre los hechos, la situación. Si no, entonces debes leer la respuesta extraordinariamente completa de paercebal [por cierto: ¡gracias!].

Mi conclusión pragmática es sorprendentemente simple: todo lo relacionado con la "codificación de caracteres" de C ++ (y STL) está sustancialmente roto e inútil. La culpa es de Microsoft o no, eso no ayudará de todos modos.

Mi solución, después de una investigación en profundidad, mucha frustración y las experiencias consiguientes es la siguiente:

  1. acepta, tienes que ser responsable por ti mismo de las cosas de codificación y conversión (y verás que gran parte de esto es bastante trivial)

  2. use std :: string para cualquier cadena codificada en UTF-8 (solo un typedef std::string UTF8String )

  3. acepte que tal objeto UTF8String es solo un contenedor tonto, pero barato. Nunca acceda ni manipule los caracteres directamente en él (no busque, reemplace, etc.). Podría, pero realmente no desea perder su tiempo escribiendo algoritmos de manipulación de texto para cadenas de múltiples bytes. Incluso si otras personas ya hicieron cosas tan estúpidas, ¡no hagas eso! ¡Déjalo ser! (Bueno, hay escenarios en los que tiene sentido ... solo use la biblioteca de ICU para esos).

  4. use std :: wstring para cadenas codificadas UCS-2 ( typedef std::wstring UCS2String ) - esto es un compromiso y una concesión al lío que introdujo la API WIN32. UCS-2 es suficiente para la mayoría de nosotros (más sobre esto más adelante ...).

  5. use las instancias UCS2String siempre que se requiera un acceso carácter por carácter (leer, manipular, etc.). Cualquier procesamiento basado en caracteres debe realizarse en una representación que no sea multibyte. Es simple, rápido, fácil.

  6. agregue dos funciones de utilidad para convertir entre UTF-8 y UCS-2:

    UCS2String ConvertToUCS2( const UTF8String &str ); UTF8String ConvertToUTF8( const UCS2String &str );

Las conversiones son sencillas, google debería ayudar aquí ...

Eso es. Use UTF8String donde la memoria sea valiosa y para todas las E / S UTF-8. Use UCS2String donde sea que la cadena deba ser analizada y / o manipulada. Puedes convertir entre esas dos representaciones en cualquier momento.

Alternativas y mejoras

  • las conversiones desde y hacia las codificaciones de caracteres de un solo byte (por ejemplo, ISO-8859-1) se pueden realizar con la ayuda de tablas de traducción simples, por ejemplo, const wchar_t tt_iso88951[256] = {0,1,2,...}; y el código apropiado para la conversión hacia y desde UCS2.

  • si UCS-2 no es suficiente, entonces cambie a UCS-4 ( typedef std::basic_string<uint32_t> UCS2String )

¿UCI u otras bibliotecas de Unicode?

Para cosas avanzadas.


Recomiendo evitar std::wstring en Windows o en cualquier otro lugar, excepto cuando lo requiera la interfaz, o en cualquier lugar cerca de las llamadas API de Windows y las respectivas conversiones de codificación como azúcar sintáctica.

Mi opinión se resume en http://utf8everywhere.org de la que soy coautor.

A menos que su aplicación esté centrada en la API, por ejemplo, principalmente la aplicación de la interfaz de usuario, la sugerencia es almacenar cadenas Unicode en std :: string y codificadas en UTF-8, realizando la conversión cerca de las llamadas a la API. Los beneficios descritos en el artículo superan la molestia aparente de la conversión, especialmente en aplicaciones complejas. Esto es doblemente para el desarrollo de múltiples plataformas y bibliotecas.

Y ahora, respondiendo a tus preguntas:

  1. Algunas razones débiles. Existe por razones históricas, donde se creía que los widechars eran la forma correcta de apoyar a Unicode. Ahora se utiliza para las API de interfaz que prefieren cadenas UTF-16. Los uso solo en la vecindad directa de tales llamadas API.
  2. Esto no tiene nada que ver con std :: string. Puede contener cualquier codificación que pongas en ella. La única pregunta es cómo tratas su contenido. Mi recomendación es UTF-8, por lo que podrá contener todos los caracteres Unicode correctamente. Es una práctica común en Linux, pero creo que los programas de Windows también deberían hacerlo.
  3. No.
  4. El carácter ancho es un nombre confuso. En los primeros días de Unicode, existía la creencia de que un carácter puede codificarse en dos bytes, de ahí el nombre. Hoy, significa "cualquier parte del carácter que tiene dos bytes de longitud". UTF-16 se ve como una secuencia de dichos pares de bytes (también conocidos como caracteres anchos). Un personaje en UTF-16 toma uno o dos pares.

¿Cuándo NO debes usar caracteres anchos?

Cuando estás escribiendo código antes del año 1990.

Obviamente, estoy siendo flip, pero en realidad, ahora es el siglo XXI. 127 caracteres han dejado de ser suficientes desde hace mucho tiempo. Sí, puedes usar UTF8, pero ¿por qué molestarse con los dolores de cabeza?


Una buena pregunta! Creo que DATA ENCODING (a veces también un CHARSET involucrado) es un MECANISMO DE EXPRESIÓN DE MEMORIA para guardar datos en un archivo o transferir datos a través de una red, así que respondo a esta pregunta como:

1. ¿Cuándo debo usar std :: wstring sobre std :: string?

Si la plataforma de programación o la función API es de un solo byte, y queremos procesar o analizar algunos datos Unicode, por ejemplo, leer desde el archivo Windows..REG o el flujo de 2 bytes de la red, debemos declarar la variable std :: wstring fácilmente. procesarlos por ejemplo: wstring ws = L "中国 a" (memoria de 6 octetos: 0x4E2D 0x56FD 0x0061), podemos usar ws [0] para obtener el carácter ''中'' y ws [1] para obtener el carácter ''国'' y ws [2] para obtener el carácter ''a'', etc.

2. ¿Puede std :: string contener todo el conjunto de caracteres ASCII, incluidos los caracteres especiales?

Sí. Pero note: American ASCII, significa que cada octeto 0x00 ~ 0xFF representa un carácter, incluido el texto imprimible como "123abc & * _ &" y usted dijo que uno especial, en su mayoría lo imprime como ''.'' Evita confundir editores o terminales. Y algunos otros países extienden su propio conjunto de caracteres "ASCII", por ejemplo, los chinos, utilizan 2 octetos para representar un carácter.

3. ¿Es std :: wstring compatible con todos los compiladores de C ++ populares?

Tal vez, o en su mayoría. He utilizado: VC ++ 6 y GCC 3.3, SI

4. ¿Qué es exactamente un "personaje ancho"?

un carácter ancho indica principalmente el uso de 2 octetos o 4 octetos para contener los caracteres de todos los países. UCS2 de 2 octetos es una muestra representativa, y además, por ejemplo, en inglés ''a'', su memoria es de 2 octetos de 0x0061 (en comparación con ASCII ''a la memoria es de 1 octeto 0x61)