Estoy leyendo Accelerated C ++ de Koenig. Escribe que "la nueva idea es que podemos usar + para concatenar una cadena y una cadena literal - o, para el caso, dos cadenas (pero no dos cadenas literales).
Bien, supongo que esto tiene sentido. Ahora, en dos ejercicios separados destinados a aclarar esto.
¿Son válidas las siguientes definiciones?
const string hello = "Hello";
const string message = hello + ",world" + "!";
Ahora, intenté ejecutar lo anterior y ¡funcionó! Entonces estaba feliz.
Luego intenté hacer el siguiente ejercicio;
const string exclam = "!";
const string message = "Hello" + ",world" + exclam;
Esto no funcionó. Ahora entiendo que tiene algo que ver con el hecho de que no se pueden concatenar dos cadenas literales, pero no entiendo la diferencia semántica entre por qué logré que el primer ejemplo funcionara (¡no es ", mundo" y "! "¿Dos literales de cadena? ¿No debería haber funcionado esto?) pero no el segundo.
const string message = "Hello" ",world" + exclam
(por ejemplo, omitiendo el primero+
) debería funcionar bien."Hello" + ", world!"
cuando tú puedes hacerlo"Hello, world!"
? Como de costumbre, C ++ tiene una solución sencilla e impresionante para un problema percibido. :-)"Hello" ", world!"
(sin+
). Hay una serie de quejas que uno podría hacer sobre C ++, pero no creo que su manejo aquí sea una de ellas. Es exactamente lo mismo que si escribiera1 / 3 + 1.5
y se quejara porque la división era una división integral. Para bien o para mal, esta es la forma en que funcionan la mayoría de los idiomas."hello" " world" == "hello world"
es útil si tiene que escribir una cadena larga y no quiere que se salga de su ventana o si quiere estar dentro de alguna restricción de longitud de línea. O si una de las cadenas está definida en una macro.Respuestas:
El
+
operador tiene asociatividad de izquierda a derecha, por lo que la expresión entre paréntesis equivalente es:Como puede ver, los dos literales de cadena
"Hello"
y",world"
se "agregan" primero, de ahí el error.Una de las dos primeras cadenas que se concatenan debe ser un
std::string
objeto:Alternativamente, puede forzar que el segundo
+
sea evaluado primero entre paréntesis esa parte de la expresión:Tiene sentido que su primer ejemplo (
hello + ",world" + "!"
) funcione porquestd::string
(hello
) es uno de los argumentos del extremo izquierdo+
. Eso+
se evalúa, el resultado es unstd::string
objeto con la cadena concatenada, y ese resultadostd::string
luego se concatena con"!"
.En cuanto a por qué no puede concatenar dos literales de cadena usando
+
, es porque un literal de cadena es solo una matriz de caracteres (const char [N]
dondeN
es la longitud de la cadena más uno, para el terminador nulo). Cuando usa una matriz en la mayoría de los contextos, se convierte en un puntero a su elemento inicial.Entonces, cuando intentas hacer
"Hello" + ",world"
, lo que realmente estás tratando de hacer es sumar dosconst char*
s, lo cual no es posible (¿qué significaría sumar dos punteros?) Y si lo fuera, no haría lo que tu quería que hiciera.Tenga en cuenta que puede concatenar cadenas literales colocándolas una al lado de la otra; por ejemplo, los dos siguientes son equivalentes:
Esto es útil si tiene un literal de cadena larga que desea dividir en varias líneas. Sin embargo, tienen que ser cadenas literales: esto no funcionará con
const char*
punteros oconst char[N]
matrices.fuente
const string message = "Hello" + (",world"+exclam);
también funcionará, debido al paréntesis explícito (¿es esa una palabra?).const string message = ((hello + ",world") + "!");
"Hello" ",world"
sintaxis es útil no solo para dividir en varias líneas, sino también cuando uno de los literales de cadena es una macro (o incluso ambos). Luego, la concatenación ocurre en tiempo de compilación.Siempre debes prestar atención a los tipos .
Aunque todos parecen cadenas
"Hello"
y",world"
son literales .Y en tu ejemplo,
exclam
es unstd::string
objeto.C ++ tiene una sobrecarga de operador que toma un
std::string
objeto y le agrega otra cadena. Cuando concatenas unstd::string
objeto con un literal, hará la conversión apropiada para el literal.Pero si intenta concatenar dos literales, el compilador no podrá encontrar un operador que tome dos literales.
fuente
std::string
con otrostd::string
, una matriz de caracteres o un solo carácter.Su segundo ejemplo no funciona porque no hay
operator +
dos literales de cadena. Tenga en cuenta que un literal de cadena no es de tipostring
, sino de tipoconst char *
. Su segundo ejemplo funcionará si lo revisa así:fuente
Desde C ++ 14, puede usar dos literales de cadena reales :
o
fuente
En el caso 1, debido al orden de las operaciones, obtiene:
(hola + ", mundo") + "!" que se resuelve en hola + "!" y finalmente para saludar
En el caso 2, como señaló James, obtienes:
("Hola" + ", mundo") + exclam que es la concatenación de 2 cadenas literales.
Espero que esté claro :)
fuente
La diferencia entre una cadena (o para ser precisos
std::string
) y un carácter literal es que para este último no hay un+
operador definido. Por eso falla el segundo ejemplo.En el primer caso, el compilador puede encontrar un valor adecuado,
operator+
siendo el primer argumento unstring
y el segundo un carácter literal (const char*
), por lo que lo usó. El resultado de esa operación vuelve a ser astring
, por lo que repite el mismo truco al agregarle"!"
.fuente