13 Stimmen

C++ Destruktor & Funktionsaufrufreihenfolge

Angenommen, ich habe das folgende Snipplet:

Foo foo;
....
return bar();

Garantiert mir nun der C++-Standard, dass bar() vor foo::~Foo() aufgerufen wird? Oder ist dies die Entscheidung des Compilers/der Implementierung?

Gracias.

16voto

mloskot Punkte 34861

Es ist ein garantiertes Verhalten. Die tatsächliche Ausführung wird wie folgt abgewickelt:

0: enter block (scope)
1: Foo::Foo()
2. evaluation of bar(); as expression in return statement
3. save result of the expression as value returned from function
4. finalize return statement to leave function to its caller (request exit from current scope)
5: exit block (scope) with call to  Foo::~Foo()

Hier sind einige Hinweise aus der Norm:

  • Was die Programmausführung im Allgemeinen garantiert

1.9 Programmausführung

10 Eine Instanz jedes Objekts mit automatischer Speicherdauer (3.7.2) wird mit jedem Eintrag in seinem Block zugeordnet.

  • El foo ist von automatischer Speicherdauer und:

3.7.2 Automatische Speicherdauer

1 Lokale Objekte explizit deklariert auto oder register oder nicht explizit deklariert static oder extern deklariert sind, haben eine automatische Speicherdauer. Die Speicherung für diese Objekte dauert so lange, bis der Block, in dem sie erzeugt wurden, beendet ist.

  • Was ist die tatsächliche Auswirkung der Return-Anweisung?

6.6.3 Die return-Anweisung

2 (...) der Wert des Ausdrucks wird an den Aufrufer der Funktion zurückgegeben

y

6.6 Sprunganweisungen (Return gehört zu Sprunganweisungen)

2 Beim Verlassen eines Bereichs (wie auch immer ausgeführt) werden Destruktoren (12.4) für alle konstruierte Objekte mit automatischer Speicherdauer (3.7.2)

  • Was garantiert, dass die Wirkung eintritt?

6.7 Erklärung

2 Im Block deklarierte Variablen mit automatischer Speicherdauer sind beim Verlassen des Blocks zerstört

y

12.4 Zerstörer

10 Destruktoren werden implizit aufgerufen (1) für ein konstruiertes Objekt mit statischer Speicherdauer (3.7.1) bei Programmende (3.6.3), (2) für ein konstruiertes Objekt mit automatischer Speicherdauer (3.7.2), wenn der Satz, in dem das Objekt erstellt wurde, beendet wird (6.7)

Es ist nicht einfach, eine einzelne Idee aus den über den gesamten C++-Standard verstreuten Details zu erfassen. Hoffentlich hilft Ihnen dieser kurze Überblick, eine solche Analyse selbst durchzuführen.

7voto

villintehaspam Punkte 8220

Ja, bar() wird vor dem Destruktor von foo aufgerufen.

So steht es in der Norm: 6.6: "Beim Verlassen eines Bereichs (wie auch immer ausgeführt) werden Destruktoren (12.4) für alle konstruierten Objekte mit automatischer Speicherdauer aufgerufen (3.7.2) (benannte Objekte oder temporäre Objekte) aufgerufen, die in diesem Bereich deklariert sind, in der umgekehrten Reihenfolge ihrer Deklaration."

Der Bereich wird erst verlassen, wenn die Return-Anweisung abgeschlossen ist.

5voto

Andrew Punkte 11722

Das Ergebnis des Aufrufs von bar() muss ausgewertet werden, bevor der Stack-Frame, der Foo enthält, bereinigt werden kann, also wird bar() vor Foo::~Foo() aufgerufen.

3voto

GManNickG Punkte 476445

Objekte werden beim Verlassen des Geltungsbereichs zerstört.

return den Geltungsbereich verlässt, aber nicht zurückkehren kann, bevor es die bar() . Ergo, bar() genannt wird.

2voto

Nicolás Punkte 7313

Stellen Sie sich vor, was wäre, wenn es return bar(foo); ? Das ist einfach hat um zu funktionieren, und es wäre dumm, wenn die Reihenfolge der Zerstörung unterschiedlich wäre, je nachdem, ob man das als Argument angibt oder nicht.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X