36 votes

Est-il sécuritaire d'utiliser (str1 + str2) .c_str ()?

J'ai testé ce code:

 #include <iostream>
#include <cstdio>
#include <string>
using namespace std;

int main()
{
    string s1("a"),s2("b");
    const char * s = (s1+s2).c_str();
    printf("%s\n",s);
}
 

Il retourne "ab".

Autant que je sache, puisque (s1 +s2) est un objet temporaire et peut disparaître d'une manière ou d'une autre (je n'en ai aucune idée), alors const char * s peut pointer vers une mémoire non définie et peut être vidé.

Alors, est-il prudent d'utiliser le .c_str() comme ça?

57voto

6502 Points 42700

Il n'est pas sûr dans votre exemple. Il est sûr cependant dans

printf("%s\n", (a + b).c_str());

La raison en est que temporaire valeurs (comme le résultat d' a + b) sont détruits à la fin de l'expression complète. Dans votre exemple, l' const char * survit à la pleine expression contenant le temporaire et du déréférencement c'est un comportement indéterminé.

La pire partie de "comportement indéfini" est que les choses peuvent apparemment le travail de toute façon... (UB code se bloque uniquement si vous créez votre démonstration devant un vaste auditoire, qui comprend vos parents ;-) )

29voto

Pierre Fourgeaud Points 10249

Dans cet exemple, nous pouvons citer la norme:

12.2 les objets Temporaires [classe.temporaire]

Objets temporaires sont détruits comme la dernière étape dans l'évaluation de la pleine expression de (1.9) que (lexicalement) contient le point où ils ont été créés. Cela est vrai même si cette évaluation se termine en levant une exception. La valeur des calculs et des effets secondaires de la destruction d'un objet temporaire sont associées avec le plein d'expression, non à une sous-expression.

C'est après le point-virgule de votre ligne:

const char * s = (s1+s2).c_str(); // <- Here

Donc ici:

printf("%s\n",s); // This line will now cause undefined behaviour.

Pourquoi? Parce que votre objet est détruit, on ne sait plus ce qui est à cet endroit aujourd'hui...

La mauvaise chose est que, avec un comportement indéterminé, votre programme peut sembler à première fois, mais... Il va se planter pour assurer au pire moment...

Vous pouvez le faire:

printf( "%s\n", (s1+s2).c_str() );

Il va travailler parce que l'objet n'est pas détruite, mais (n'oubliez pas, après le point-virgule...).

5voto

Miguel Prz Points 8136

Ce n'est pas sûr, mais vous pouvez facilement affecter une nouvelle variable, et le pointeur sera en sécurité dans la portée de cette variable:

 string s1("a"), s2("b") , s3;
s3 = s1 + s2;
printf("%s\n", s3.c_str());

//other operations with s3
 

4voto

Pete Becker Points 27371

Comme la plupart des constructions de programmation, il est "sûr" si vous l'utilisez correctement, et ce n'est pas "sûr" si vous êtes au bout du rouleau. Dans ce cas, en utilisant correctement les moyens de payer l'attention sur l'objet des durées de vie. L' + opérateur crée un objet temporaire qui sera détruite à la fin de l'instruction, et le retour de l' const char* n'est plus valide après la déclaration qui l'a créé. De sorte que vous pouvez passer à la suite de l' c_str() directement à une fonction, mais vous ne pouvez pas enregistrer le pointeur et l'utiliser plus tard.

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