Quelle est la durée de vie de std :: ssortingng :: c_str ()?

Dans l’un de mes programmes, je dois interfacer avec un code hérité qui fonctionne avec const char* .

Disons que j’ai une structure qui ressemble à:

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

Mon application de niveau supérieur ne traite que de std::ssortingng , alors j’ai pensé à utiliser std::ssortingng::c_str() pour récupérer les pointeurs const char* .

Mais quelle est la durée de vie de c_str() ?

Puis-je faire quelque chose comme ça sans faire face à un comportement indéfini?

 { std::ssortingng server = "my_server"; std::ssortingng 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 } 

Ou suis-je censé copier immédiatement le résultat de c_str() à un autre endroit?

Je vous remercie.

Le résultat c_str() devient invalide si la std::ssortingng est détruite ou si une fonction membre non-const de la chaîne est appelée. Donc, généralement, vous voudrez en faire une copie si vous avez besoin de la conserver.

Dans le cas de votre exemple, il apparaît que les résultats de c_str() sont utilisés en toute sécurité, car les chaînes ne sont pas modifiées dans cette scope. (Cependant, nous ne soaps pas ce que use_foo() ou ~Foo() peuvent faire avec ces valeurs, si elles copient les chaînes ailleurs, alors elles doivent faire une copie vraie, et pas seulement copier les pointeurs de caractères.)

Techniquement, votre code est correct.

MAIS vous avez écrit de telle manière qu’il est facile de casser pour quelqu’un qui ne connaît pas le code. Pour c_str (), la seule utilisation sûre est lorsque vous la transmettez en tant que paramètre à une fonction. Sinon, vous vous exposez à des problèmes de maintenance.

Exemple 1:

 { std::ssortingng server = "my_server"; std::ssortingng 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 } 

Donc, pour l’entretien, il est évident que:

Meilleure solution:

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

Mais si vous avez des chaînes const, vous n’en avez pas réellement besoin:

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

D’ACCORD. Pour une raison quelconque, vous les voulez en tant que chaînes:
Pourquoi ne pas les utiliser uniquement dans l’appel:

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

Il est valide jusqu’à ce que l’un des événements suivants arrive à l’object de ssortingng correspondant:

  • l’object est détruit
  • l’object est modifié

Vous êtes d’accord avec votre code, à moins que vous ne modifiiez ces objects après que c_str() ait été copié dans foo mais avant que use_foo() soit appelé.

La valeur de retour de c_str () n’est valide que jusqu’au prochain appel d’une fonction membre non constante pour la même chaîne.

Le caractère const char* renvoyé par c_str() n’est valide que jusqu’au prochain appel non-const à l’object std::ssortingng . Dans ce cas-ci, tout va bien parce que votre std::ssortingng est toujours dans la scope de Foo et que vous ne faites aucune autre opération qui changerait la chaîne en utilisant foo.

Tant que la chaîne n’est pas détruite ou modifiée, l’utilisation de c_str () est correcte. Si la chaîne est modifiée à l’aide d’un fichier c_str () précédemment renvoyé, l’implémentation est définie.