2010-06-14 7 views
17

Wird ein temporärer Teil eines Arguments für einen Funktionsaufruf erstellt, der garantiert bleibt, bis die aufgerufene Funktion endet, auch wenn das temporäre Element nicht direkt an die Funktion übergeben wird?Wann werden Provisorien, die im Rahmen eines Funktionsaufrufs erstellt wurden, zerstört?

ist es so gut wie keine Chance, dass kohärent war, also hier ein Beispiel:

class A { 
public: 
    A(int x) : x(x) {printf("Constructed A(%d)\n", x);} 
    ~A() {printf("Destroyed A\n");} 

    int x; 
    int* y() {return &x;} 
}; 

void foo(int* bar) { 
    printf("foo(): %d\n", *bar); 
} 

int main(int argc, char** argv) { 
    foo(A(4).y()); 
} 

Wenn A(4) wurden direkt an foo weitergegeben, es wäre auf jeden Fall erst nach dem foo Anruf beendet zerstört werden, sondern ich rufe eine Methode auf der temporären und verlieren jegliche Bezugnahme darauf. Ich würde instinktiv denken, dass die temporäre A würde zerstört werden, bevor foo startet sogar, aber das Testen mit GCC 4.3.4 zeigt, ist es nicht; der Ausgang ist:

Konstruiert A (4)
foo(): 4
Zerstörte A

Die Frage ist, ist GCC das Verhalten durch die spec garantiert? Oder ist es einem Compiler erlaubt, das temporäre A vor dem Aufruf an foo zu zerstören, den Zeiger auf seinen Member ungültig zu machen, den ich verwende?

Antwort

17

Temporäre Objekte existieren bis zum Ende des vollständigen Ausdrucks, in dem sie erstellt werden.

In Ihrem Beispiel des A Objekt von A(4) erstellt wird mindestens bestehen, bis der Ausdruck nur nach der Rückkehr aus dem Aufruf von foo() endet.

Dieses Verhalten wird von dem Sprachstandard garantiert:

Temporäre Objekte werden als letzten Schritt zerstören in den Voll Ausdruck Bewertung (1.9), dass (lexikalisch) enthält den Punkt, an dem sie erstellt wurden. Dies gilt auch dann, wenn diese Auswertung mit dem Auslösen einer Ausnahme endet (C++ 03 §12.2/3).

Die Lebensdauer der temporären kann durch Bindung eine Referenz darauf erweitert werden (in diesem Fall seine Lebensdauer bis zum Ende der Laufzeit der Referenz verlängert wird), oder indem es als Initialisierer in einem Konstruktor des Initialisierer Verwendung Liste (in diesem Fall wird seine Lebensdauer verlängert, bis das zu konstruierende Objekt vollständig aufgebaut ist).

+0

Ehrfürchtig zerstört Dank Ihnen und Jerry für den Verweis in der Spezifikation zu finden, hatte ich Schwierigkeiten, es –

2

Das temporäre dauert bis zum Ende des Ausdrucks es ist Teil von - in diesem Fall ist ein Funktionsaufruf.

-1

Die Lebensdauer Ihres temporären Objekt A(4) lange genug dauern wird y()

Der Speicher, auf der Rückkehr von y() zu nennen, ist nicht zuverlässig, je nach Threading und Zuweisungen es neu zugewiesen werden können und den Wert vor der geändert Anruf an foo() macht davon Gebrauch.

+0

Hmmm , anscheinend gibt MSVC mir eine nicht standardisierte Antwort, gut, um den Standard zu lernen. –

5

§12.2/3: "Temporäre Objekte werden als letzter Schritt bei der Auswertung des vollständigen Ausdrucks (1.9) zerstört, der (lexikalisch) den Punkt enthält, an dem sie erstellt wurden."

IOW, du bist sicher -.. Das A Objekt muss erst nach foo kehrt