2010-04-29 15 views
7

Por lo tanto, quiero obtener una mejor comprensión de cómo funcionan los literales de cadenas en C++. Me preocupan más las situaciones en las que se está asignando la dirección de un literal de cadena a un puntero y pasándolo por alto. Por ejemplo:¿Qué tan seguros y confiables son los Literals de C++ String?

char* advice = "Don't stick your hands in the toaster."; 

Ahora digamos que acabo de pasar esta cadena copiando punteros durante la duración del programa. Claro, probablemente no sea una buena idea, pero tengo curiosidad por saber qué estaría sucediendo detrás de escena.

Para otro ejemplo, digamos que hacemos una función que devuelve una cadena literal:

char* foo() 
{ 
    // function does does stuff 
    return "Yikes!"; // somebody's feeble attempt at an error message 
} 

Ahora digamos que esta función se llama muy a menudo, y la cadena literal sólo se utiliza la mitad del tiempo que se llama :

// situation #1: it's just randomly called without heed to the return value 
foo(); 

// situation #2: the returned string is kept and used for who knows how long 
char* retVal = foo(); 

En la primera situación, ¿qué está sucediendo realmente? ¿La cadena acaba de crearse pero no se usa, y nunca se desasigna?

En la segunda situación, ¿la cadena se mantendrá mientras el usuario lo necesite? ¿Qué sucede cuando ya no es necesario ... se liberará esa memoria en ese momento (asumiendo que ya no hay nada que apunte a ese espacio)?

No me malinterpreten, no estoy pensando en utilizar literales de cadena como este. Estoy planeando usar un contenedor para mantener mis cadenas bajo control (probablemente std :: string). En su mayoría solo quiero saber si estas situaciones podrían causar problemas, ya sea para la administración de la memoria o datos corruptos.

+8

Los literales de cadenas C++ son perfectamente seguros y confiables. Son los programadores quienes usan los literales de cadena que no son seguros y confiables. –

+0

Esto es lo que estaba pensando; Solo necesitaba confianza, supongo. Gracias. :) –

Respuesta

22

Los literales de cadena tienen el tipo const char[N] (donde N es la longitud + 1) y están asignados estáticamente. No necesita preocuparse por problemas de memoria; si se utiliza una cadena en su programa, todo se maneja por usted y reside en algún lugar de la memoria del programa (generalmente de solo lectura).

Es decir, estos son "lo mismo":

static const char str[] = "a string"; 
"a string" 

Cuando se señala a una cadena literal, que está señalando el primer carácter en la matriz. De hecho, como el tipo es const char[], solo es seguro señalarlo a través del const char*. La conversión de cadena literal a char* está en desuso y es insegura.

// the "same" 
static const char str[] = "a string"; 
const char* strPtr = str; // decays 

const char* s1 = "a string"; 
char* s2 = "a string"; // allowed, implicit const_cast 

*s1 = 'A'; // not allowed, it's const 
*s2 = 'B'; // allowed, it's not const (but leads to undefined behavior) 
+5

"La conversión de cadena literal a char * está en desuso y es insegura". Sí. Necesita cadenas escritas si lo hizo en alguna parte. De todos modos, NO HAGAS ESO. – Joshua

+1

Sí, gracias por explicar el aspecto de la const en detalle. Sabía que eran constantes, pero pensé que dejaría la explicación a alguien que los entendiera mejor que yo :) :) –

+2

Lo has dicho todo, por lo que yo sé. –

1

En primer lugar, declarar el valor de retorno de foo como const, porque los literales de cadena son constantes que no se pueden cambiar sin causar la temida "comportamiento indefinido". Esto forzará a cualquier puntero que use el valor de retorno de foo a declararse también como const, y potencialmente limitar el daño que puede (por lo general no intencionalmente) hacerse. Los literales de cadena se almacenan en el área 'texto' de un ejecutable binario; no se crean como tales en tiempo de ejecución.

Cuestiones relacionadas