81 votes

C++ : Durée de vie des arguments temporaires ?

Lors de la création d'une nouvelle instance d'un MyClass comme argument d'une fonction comme celle-ci :

class MyClass
{
  MyClass(int a);
};    

myFunction(MyClass(42));

La norme donne-t-elle des garanties sur la synchronisation du destructeur ?

Plus précisément, puis-je supposer qu'il sera appelé avant l'instruction suivante après l'appel à la fonction myFunction() ?

1 votes

124voto

sbi Points 100828

Les objets temporaires sont détruits à la fin de l'expression complète dont ils font partie.

Une expression complète est une expression qui n'est pas une sous-expression d'une autre expression. En général, cela signifie qu'elle se termine à la position ; (ou ) pour if , while , switch etc.) indiquant la fin de la déclaration. Dans votre exemple, c'est la fin de l'appel de fonction.

Notez que vous pouvez prolonger la durée de vie des temporaires en les liant à un fichier const référence. Cela permet d'étendre leur durée de vie à celle de la référence :

MyClass getMyClass();

{
  const MyClass& r = getMyClass(); // full expression ends here
  ...
} // object returned by getMyClass() is destroyed here

Si vous n'avez pas l'intention de modifier l'objet retourné, c'est une astuce intéressante pour éviter de copier l'appel au constructeur (par rapport à l'option MyClass obj = getMyClass(); ), au cas où l'optimisation de la valeur de retour ne serait pas appliquée. Malheureusement, elle n'est pas très connue. (Je suppose que la sémantique de déplacement de C++11 la rendra moins utile, cependant).

1 votes

+1 belle réponse. Mais je pense que vous voulez dire ) au lieu de } pour if, while, switch etc ? if(f(string())) { ... } ne permettra sûrement pas à la chaîne de survivre jusqu'à } :)

0 votes

@Johannes : Non, n'est-ce pas ? C'est ce que je pensais.

1 votes

@sbi l'expression complète se termine à la ) . L'ensemble peut être une "déclaration complète" mais pas une "expression complète". Idem dans for(iterator i = begin(); i<end; i++) { ... } le compilateur n'est pas obligé de garder les itérateurs temporaires résultant de i++ en vie jusqu'à la fin de l'instruction for, bien sûr. Les temporaires ne vivront que jusqu'à la fin de l'expression complète, qui est l'instruction ) dans ce cas également.

29voto

Steve Jessop Points 166970

Tout le monde a cité à juste titre 12.2/3 ou similaire, ce qui répond à votre question :

Les objets temporaires sont détruits lors de la dernière étape de l'évaluation de l'expression expression complète qui (lexicalement) contient le point où ils ont été créés.

Je trouve amusant que sur la page suivante dans mon impression de la norme, 12.2/4 dit :

Il existe deux contextes dans lesquels temporaires sont détruits à un moment point différent de la fin de l'expression expression complète.

Aucun des deux ne s'applique à votre exemple, ils concernent tous deux l'utilisation de temporaires dans les initialisateurs. Mais cela montre bien qu'il faut garder son sang-froid lorsqu'on a affaire à une bête rusée comme la norme C++.

1 votes

Ce serait génial si la deuxième citation était intentionnellement aligné de telle sorte qu'il commence sur une page et se termine sur la suivante :-)

4 votes

Wow, merci d'avoir mentionné cette "exception". Les temporaires dans les initialisateurs étaient précisément le cas qui m'a piqué.

10voto

La norme offre effectivement des garanties - à partir de la section 12.2/5 :

Un temporaire lié à une référence dans un appel de fonction (5.2.2) persiste jusqu'à l'achèvement de l'expression expression complète contenant l'appel

Cependant, dans votre code, il n'est pas clair si le paramètre est passé par référence ou par valeur, bien qu'à un moment donné, un constructeur de copie qui prend une référence sera utilisé.

3voto

Mike Mueller Points 1007

Dans la section 12.2, Temporary Objects, clause 3, la norme ANSI/ISO C indique : "... Les objets temporaires sont détruits lors de la dernière étape de l'évaluation de l'expression complète qui contient (lexicalement) le point où ils ont été créés."

Ce concept est étroitement lié à celui de Points de séquence . Lorsqu'un point de séquence est atteint, il est garanti que tous les effets secondaires des expressions ont eu lieu.

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