Introducción: dos cadenas, un mismo dolor de cabeza
\n\nTodo desarrollador de C++ tarde o temprano se enfrenta al dilema: std::string o std::wstring? A simple vista, ambos son cadenas, ambos provienen de STL, pero se comportan de maneras completamente diferentes. Esta cuestión se vuelve especialmente crítica al trabajar con texto multilingüe, emojis o caracteres jeroglíficos.
Si programas en C++ y deseas que tu aplicación maneje correctamente «¡Hola, mundo!» en ruso, japonés o árabe, es indispensable comprender la diferencia entre std::string y std::wstring. En este artículo, analizaremos ambos enfoques, los compararemos según parámetros clave y decidiremos cuándo usar cada uno.
Este material se basa en una pregunta real de Stack Overflow que ha acumulado miles de visitas. Lo hemos adaptado con fines educativos, añadiendo ejemplos y una estructura clara.\n\n
std::string: clásico y simple
\n\nstd::string es un alias para std::basic_string<char>. Cada carácter ocupa 1 byte. Históricamente, char se usaba para caracteres ASCII, pero hoy en día suele almacenar datos en codificación UTF-8 (o simplemente bytes).
Ventajas de std::string
\n- \n
- Ahorro de memoria — 1 byte por carácter para ASCII/UTF-8. \n
- Compatibilidad — funciona con la mayoría de las bibliotecas, incluidas las funciones de C (
strlen,strcpy). \n - Velocidad — menor sobrecarga de asignación. \n
- Ubicuidad — estándar de facto para la transmisión de datos por red y en JSON. \n
Desventajas de std::string
\n- \n
- Confusión con las codificaciones —
std::stringno sabe en qué codificación se almacenan los datos. Puedes almacenar UTF-8 en él, pero.size()devolverá la cantidad de bytes, no de caracteres. \n - Problemas con Unicode — iterar sobre la cadena puede dividir un carácter multibyte. \n
- Sin soporte nativo para caracteres anchos — para trabajar con Unicode fuera de UTF-8, es necesario usar bibliotecas de terceros. \n
// Ejemplo: std::string con UTF-8\n#include <iostream>\n#include <string>\n\nint main() {\n std::string s = "¡Hola, mundo!";\n std::cout << "Longitud en bytes: " << s.size() << std::endl; // 13 bytes\n std::cout << "Primer carácter (como char): " << s[0] << std::endl; // Basura: primer byte UTF-8\n return 0;\n}\n\nEn este ejemplo, s[0] no devolverá '¡', sino el primer byte del carácter de dos bytes '¡' (0xC2). Este es un error común entre principiantes.
std::wstring: el poder de los caracteres anchos
\n\nstd::wstring es std::basic_string<wchar_t>. El tamaño de wchar_t depende de la plataforma: 2 bytes en Windows (UTF-16) y 4 bytes en Linux/macOS (UTF-32).
Ventajas de std::wstring
\n- \n
- Tamaño de carácter fijo (en una plataforma específica) — simplifica el trabajo con Unicode. \n
- Soporte directo de configuraciones regionales — en Windows, todas las funciones de WinAPI trabajan con
wchar_t. \n - Menos problemas con caracteres multibyte — cada carácter es un elemento de la cadena. \n
Desventajas de std::wstring
\n- \n
- El tamaño depende de la plataforma — el código puede comportarse de manera diferente en Windows y Linux. \n
- Mayor consumo de memoria — 2 o 4 bytes por carácter, incluso para ASCII. \n
- Problemas de compatibilidad — no todas las bibliotecas admiten
wchar_t. \n - Pares sustitutos — en UTF-16, algunos caracteres (por ejemplo, emojis) ocupan 2
wchar_t, lo que vuelve a crear el problema de «carácter ≠ elemento». \n
// Ejemplo: std::wstring en Windows\n#include <iostream>\n#inclu