Destruction des cordes dans des temporaires exceptions lancées
-
19-09-2019 - |
Question
Considérez le code suivant:
std::string my_error_string = "Some error message";
// ...
throw std::runtime_error(std::string("Error: ") + my_error_string);
La chaîne passée à runtime_error est temporaire retourné par la operator+
de chaîne. Supposons que cette exception est gérée quelque chose comme:
catch (const std::runtime_error& e)
{
std::cout << e.what() << std::endl;
}
Quand est-ce le temporaire retourné par la chaîne de operator+
détruite? Est-ce que la langue spec a quelque chose à dire à ce sujet? En outre, runtime_error suppose a un argument const char*
et a été jeté comme ceci:
// Suppose runtime_error has the constructor runtime_error(const char* message)
throw std::runtime_error((std::string("Error: ") + my_error_string).c_str());
Quand la chaîne temporaire retourné par l'opérateur + détruit? Serait-il être détruit avant que le bloc catch tente d'imprimer, et est-ce pourquoi runtime_error accepte un std :: string et non un const char *?
La solution
Comme un objet temporaire (12.2), le résultat de la +
sera détruite en tant que dernière étape dans l'évaluation de la -expression complète (1,9 / 9) qui le contient. Dans ce cas, le expression complète est expression jeter .
touche expression construit un objet temporaire (la exception objet ) (15.1) (std::runtime_error
dans ce cas). Tous les dans les temporaires expression jeter seront détruites après la exception objet a été construit. L'exception est levée une seule fois l'évaluation de la jeter expression a terminé, comme la destruction de temporaires fait partie de cette évaluation, ils seront détruits avant la destruction des variables automatiques construites depuis le bloc d'essai a été saisi (15.2) et avant que le gestionnaire est entré.
Le post-condition sur le constructeur de runtime_error
est que what()
renvoie quelque chose qui strcmp
considère égale à ce que c_str()
sur le passé dans les déclarations d'argument. Il est une possiblilité théorique qu'une fois le std::string
passé comme argument du constructeur est détruit, le runtime_error
de what()
pourrait retourner quelque chose de différent, même si ce serait une mise en œuvre douteuse et il devrait encore être une chaîne se terminant par null de quelque sorte, il couldn » t retourner un pointeur vers un c_str()
périmé d'une chaîne morte.
Autres conseils
runtime_error est une classe qui contient une chaîne. Cette chaîne sera géré pour vous par les mécanismes normaux de construction et de destruction C ++. Si elle contenait un char *, alors que devrait être géré de façon explicite, mais vous auriez encore de ne rien faire comme utilisateur de runtime_error.
En dépit de ce que vous pouvez lire ailleurs sur Internet, C ++ est conçu pour presque toujours faire « la chose raisonnable » - vous avez réellement essayer assez difficile à briser ce comportement raisonnable, mais bien sûr, il est impossible de le faire.
Notez que la classe d'exception runtime_error fait une copie de la chaîne passée dans le constructeur. Alors, quand vous appelez .que () sur l'objet d'exception, vous n'êtes pas revenir la même instance de chaîne exacte que vous avez passé dans.
Donc, pour répondre à votre question, vous demandez le temporaire au sujet est détruit « au point-virgule » de l'expression qui contient (ce qui est vrai à la fois votre première et la deuxième version de la question), mais comme je l'ai dit, ce n'est pas intéressant, parce qu'une copie a déjà été fait.