what str que mid library hace does cpp c_str c++ string cstring

c++ - que - ¿Qué es std:: string:: c_str() lifetime?



string library c++ (6)

En uno de mis programas, tengo que interactuar con algún código heredado que funcione con const char* .

Digamos que tengo una estructura que se ve así:

struct Foo { const char* server; const char* name; };

Mi aplicación de nivel superior solo trata con std::string , así que pensé en usar std::string::c_str() para recuperar los punteros const char* .

Pero, ¿ c_str() la vida de c_str() ?

¿Puedo hacer algo como esto sin enfrentar un comportamiento indefinido?

{ std::string server = "my_server"; std::string name = "my_name"; Foo foo; foo.server = server.c_str(); foo.name = name.c_str(); // We use foo use_foo(foo); // Foo is about to be destroyed, before name and server }

¿O se supone que debo copiar inmediatamente el resultado de c_str() a otro lugar?

Gracias.


El const char* devuelto por c_str() solo es válido hasta la siguiente llamada no consistente al objeto std::string . En este caso, estás bien porque tu std::string todavía está en el alcance durante la vida útil de Foo y no estás haciendo ninguna otra operación que pueda cambiar la cadena mientras usas foo.


El resultado c_str() no es válido si se destruye std::string o si se llama a una función miembro no consistente de la cadena. Por lo tanto, generalmente querrá hacer una copia si necesita mantenerla.

En el caso de su ejemplo, parece que los resultados de c_str() se usan de manera segura, porque las cadenas no se modifican mientras están en ese ámbito. (Sin embargo, no sabemos lo que use_foo() o ~Foo() podrían estar haciendo con esos valores, si copian las cadenas en otro lugar, entonces deberían hacer una copia verdadera, y no solo copiar los punteros de char .)


El valor de retorno de c_str () es válido solo hasta la próxima llamada de una función de miembro no constante para la misma cadena


Es válido hasta que ocurra lo siguiente con el objeto de string correspondiente:

  • el objeto es destruido
  • el objeto se modifica

Está bien con su código, a menos que modifique esos objetos de string después de que c_str() s se copien en foo pero antes de use_foo() .


Siempre que la cadena no se destruya o modifique, usar c_str () está bien. Si la cadena se modifica utilizando un c_str () previamente devuelto, se define la implementación.


Técnicamente tu código está bien.

PERO usted ha escrito de tal manera que hace que sea fácil romper para alguien que no conoce el código. Para c_str (), el único uso seguro es cuando lo pasa como parámetro a una función. De lo contrario, usted se abre a problemas de mantenimiento.

Ejemplo 1:

{ std::string server = "my_server"; std::string name = "my_name"; Foo foo; foo.server = server.c_str(); foo.name = name.c_str(); // // Imagine this is a long function // Now a maintainer can easily come along and see name and server // and would never expect that these values need to be maintained as // const values so why not re-use them name += "Martin"; // Oops now its broken. // We use foo use_foo(foo); // Foo is about to be destroyed, before name and server }

Por lo tanto, para el mantenimiento, hazlo obvio:

Mejor solución:

{ // Now they can''t be changed. std::string const server = "my_server"; std::string const name = "my_name"; Foo foo; foo.server = server.c_str(); foo.name = name.c_str(); use_foo(foo); }

Pero si tienes cadenas const no las necesitas realmente:

{ char const* server = "my_server"; char const* name = "my_name"; Foo foo; foo.server = server; foo.name = name; use_foo(foo); }

DE ACUERDO. Por algún motivo, los quieres como cadenas:
¿Por qué no usarlos solo en la llamada?

{ std::string server = "my_server"; std::string name = "my_name"; // guaranteed not to be modified now!!! use_foo(Foo(server.c_str(), name.c_str()); }