56 votes

Les valeurs de retour des fonctions sont-elles des objets automatiques et donc garanties d'être détruites ?

Dans [except.ctor], la norme ( N4140 ) garantit que :

...les destructeurs sont invoqués pour tous les objets automatiques construits depuis que le bloc d'essai a été entré...

Cependant, dans l'exemple suivant, le vide sortie prouve que la valeur de retour de la fonction foo n'est pas détruite, bien qu'elle ait été construite. Compilé en utilisant g++ (5.2.1) et clang++ (3.6.2-1) et avec les options -O0 -fno-elide-constructors -std=c++14 .

struct A { ~A() { cout << "~A\n"; } };

struct B { ~B() noexcept(false) { throw 0; } };

A foo() {
  B b;
  return {};
}

int main() {
  try { foo(); }
  catch (...) { }
}

Est-ce un bogue à la fois dans g++ et clang++, ou les valeurs de retour des fonctions ne sont-elles pas ne sont pas considérées comme des objets automatiques, ou est-ce une faille dans le langage C++ ?

Dans aucun de [stmt.return], [expr.call] ou [dcl.fct] je n'ai pu trouver clairement si une valeur de retour de fonction est considérée comme un objet automatique. automatique. Les indications les plus proches que j'ai trouvées sont 6.3.3 p2 :

...Une déclaration de retour peut impliquer la construction et la copie ou le déplacement d'un objet temporaire...

et 5.2.2 p10 :

Un appel de fonction est une lvalue si le type de résultat est une lvalue. ou une référence rvalue au type de fonction, une xvalue si le type de résultat est un type rv. type de résultat est une référence rvalue au type d'objet, et une prvalue sinon.

45voto

TartanLlama Points 1461

Les valeurs de retour des fonctions sont considérées comme des temporaires, et la construction de la valeur de retour est séquencée avant la destruction des locales.

Malheureusement, cela n'est pas spécifié dans la norme. Il existe un défaut ouvert qui décrit cette situation et propose une formulation pour résoudre le problème

[...] Une instruction de retour avec un opérande de type void ne doit être utilisée que dans une fonction dont le type de retour est cv void. Une instruction de retour avec tout autre opérande ne doit être utilisée que dans une fonction dont le type de retour n'est pas cv void ; l'instruction de retour initialise l'objet ou la référence qui doit être renvoyé par une initialisation par copie (8.5 [dcl.init]) à partir de l'opérande. [...]

La copie-initialisation de l'entité retournée est séquencée avant la destruction des temporaires à la fin de l'expression complète établie par l'opérande de l'instruction de retour, qui, à son tour, est séquencée avant la destruction des variables locales (6.6 [stmt.jump]) du bloc entourant l'instruction de retour.

Puisque les valeurs de retour des fonctions sont temporaires, elles ne sont pas couvertes par la norme destructors are invoked for all automatic objects citation au début de votre message. Cependant, [class.temporary]/3 dit :

[...] 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. Ceci est vrai même si cette évaluation aboutit à la levée d'une exception. . [...]

Je pense donc que vous pouvez considérer cela comme un bogue dans GCC et Clang.

Ne pas lancer de destructeurs ;)

7voto

Sebastian Redl Points 18816

Il s'agit d'un bogue, et pour une fois, MSVC s'y prend bien : il imprime "~A".

7voto

AC Voltage Points 84

J'ai modifié votre code et je pense que maintenant, à partir de la sortie, nous pouvons voir que A n'est pas détruit.

#include<iostream>

using namespace std;

struct A {
    ~A() { cout << "~A\n"; }
    A() { cout << "A()"; }
};

struct B {
    ~B() noexcept( false ) { cout << "~B\n"; throw(0); }
    B() { cout << "B()"; }
};

A foo() {
    B b;
    return;
}

int main() {
    try { foo(); }
    catch (...) {}
}

Et le résultat est :

B()A()~B

Donc oui, cela pourrait être un bug.

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