118 votes

Qu'est-ce que la durée de vie std :: string :: c_str ()?

Dans un de mes programmes, j'ai une interface avec un code existant qui fonctionne avec const char*.

Disons que j'ai une structure qui ressemble à:

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

Mon niveau supérieur de demande ne traite que d' std::string, alors j'ai pensé à l'aide d' std::string::c_str() de revenir const char* des pointeurs.

Mais qu'est-ce que la durée de vie d' c_str() ?

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

{
  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
}

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

Je vous remercie.

97voto

Kristopher Johnson Points 34554

L' c_str() résultat devient invalide si l' std::string est détruit ou si un non-const fonction de membre de la chaîne est appelé. Donc, en général, vous voulez faire une copie de celui-ci si vous avez besoin de le garder.

Dans le cas de votre exemple, il semble que les résultats de l' c_str() sont utilisés en toute sécurité, parce que les cordes ne sont pas modifiés dans le cadre de ce champ d'application. (Toutefois, nous ne savons pas ce qu' use_foo() ou ~Foo() peut être fait avec ces valeurs, si elles copier les chaînes ailleurs, alors qu'ils devraient faire une vrai copie, et pas seulement de déplacer l' char des pointeurs).

27voto

Loki Astari Points 116129

Techniquement, votre code est bien.

MAIS vous avez écrit dans une telle manière qui le rend facile à briser pour quelqu'un qui ne connais pas le code. Pour c_str() la seule sécurité d'utilisation, c'est quand vous le passer en paramètre à une fonction. Sinon, vous vous exposez à des problèmes de maintenance.

Exemple 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
}

Donc, pour l'entretien à l'évidence:

Meilleure solution:

{
  // 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);    
}

Mais si vous avez const chaînes que vous n'avez pas réellement besoin d'eux:

{
  char const* server = "my_server";
  char const* name   = "my_name";

  Foo foo;
  foo.server = server;
  foo.name   = name;

  use_foo(foo);
}

OK. Pour une raison que vous les voulez comme des chaînes de caractères:
Pourquoi ne pas les utiliser uniquement à l'appel:

{
  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());
}

8voto

sharptooth Points 93379

Il est valide jusqu'à ce que l'un des événements suivants survienne pour l'objet string :

  • l'objet est détruit
  • l'objet est modifié

Votre code vous convient, sauf si vous modifiez les objets string après que c_str() s sont copiés dans foo mais avant que use_foo() soit appelé.

4voto

DumbCoder Points 4097

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

2voto

CharlesB Points 27070

Tant que la chaîne n'est ni détruite ni modifiée, c_str () est acceptable. Si la chaîne est modifiée à l'aide d'un fichier c_str () précédemment renvoyé, sa mise en œuvre est définie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X