string s = "Hello world";
char* s2 = s.c_str();
s2 se asignarán en la pila, o en el montón? En otras palabras ... ¿Tendré que eliminar s2?
s2
está en la pila, sí. Pero, es un puntero a un personaje (que en este caso pasa a ser el primer personaje en una representación ASCIIZ del contenido de texto de s
). Ese texto en sí es donde el objeto s
sintió ganas de construir esa representación.Las implementaciones pueden hacer eso como quieran, pero la opción de implementación crucial para std::string
es si proporcionan una "optimización de cadena corta" que permite insertar cadenas muy cortas directamente en el objeto s
y si "Hello world" es lo suficientemente corto beneficiarse de esa optimización:
- si es así, entonces
s2
apuntaría a apilar memoria asignada dentro s
- de otro modo, en el interior
s
habría un puntero a la memoria/montón asignado-tienda libre en la que el "Hola mundo \ 0 "contenido cuya dirección es devuelta por .c_str()
aparecería, y s2 sería una copia de ese valor.
Tenga en cuenta que es c_str()
const
, por lo que para su código para compilar es necesario cambiar a const char* s2 = ...
.
No es necesario que elimine s2, no. Los datos a los que los puntos s2 aún son propiedad y están gestionados por el objeto s
, serán invalidados por cualquier llamada a métodos que no sean const
de s
o por s
que salgan del alcance.
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
Se s2 estar ahora en el montón, ya que su origen estaba en el montón?
Este código no compila, como s
no es un puntero y una cadena no tiene un constructor como string(std::string*)
. Se podría cambiarlo a cualquiera:
string* s = new string("Hello, mr. heap...");
... o ...
string s = *new string("Hello, mr. heap...");
Este último crea una pérdida de memoria y no sirve a ningún propósito útil, así que vamos a suponer que la primera. Entonces:
char* s2 = s.c_str();
... tiene que convertirse ...
char* s2 = s->c_str();
Will s2 estar ahora en el montón, ya que su origen estaba en el montón?
Sí. En todos los escenarios, especialmente si s
sí mismo es en el montón, entonces:
- incluso si hay un corto búfer de optimización cadena dentro
s
a la que c_str()
produce un puntero, que debe ser en el montón, de lo contrario
- si
s
usa un puntero a otra memoria para almacenar el texto, esa memoria también se asignará desde el montón.
Pero, de nuevo, aún sabiendo con certeza que s2
apunta a la pila de memoria asignada, su código no tiene que desasignar que la memoria - que se hará automáticamente cuando se elimina s
:
string* s = new string("Hello, mr. heap...");
const char* s2 = s->c_str();
...use s2 for something...
delete s; // "destruct" s and deallocate the heap used for it...
De Por supuesto, generalmente es mejor usar string s("xyz");
a menos que necesite una vida más allá del alcance local, y std::unique_ptr<std::string>
o std::shared_ptr<std::string>
de lo contrario.
¿Interesante, entonces, nunca liberarías el char * porque al hacerlo liberarías datos internos en la cadena? c_str() contiene literalmente la misma dirección que los datos reales que está usando la cadena? ¿Múltiples llamadas a .c_str() devolverían la misma dirección de esa manera? (Solo aclaro para que sepa que entiendo) –
@Georges la respuesta a algunas de esas preguntas depende de si está usando el último estándar o el anterior. Es posible que desee aclarar cuál le interesa. –
@ R.MartinhoFernandes Mejor ir con el último estándar. Sin embargo, sería interesante saber qué tan reciente es esta norma –