2010-07-15 8 views
9

Eine grundlegende Frage, dass ich mir der Antwort nicht sicher bin. Ist die Folgefunktion gültig?C++ return reference/stack memory

std::vector<int> & test_function() { 
    std::vector<int> x; 

    // do whatever 

    return x; 
} 

Wenn ja, warum? Sollte das Programm nicht x aus dem Stapel löschen, nachdem die Funktion zurückkehrt? Vielen Dank.

Antwort

11

Das Verhalten ist nicht definiert. Sie sollten keine Verweise auf lokale Variablen zurückgeben.

+1

Verdammt, schlag mich dazu! – Anthony

+1

Der Code, der angezeigt wird, enthält (für sich) kein undefiniertes Verhalten. Die UB würde in anderem Code passieren, der diese Funktion aufruft. –

8

Die Funktion ist wohlgeformt (syntaktisch korrekt), aber sobald die Funktion zurückkehrt, ist die zurückgegebene Referenz ungültig und kann nicht verwendet werden.

Um zu verdeutlichen: der betreffende Code tut nicht aufrufen undefinierte Verhalten. Sie können diese Funktion sicher aufrufen, solange Sie nicht den Rückgabewert verwenden, zB das gilt:

test_function(); // ok 

Wenn Sie jedoch versuchen, den Rückgabewert zu verwenden (dh mit ihm einen anderen Bezug zu initialisieren oder zu kopieren die referent in ein anderes Objekt), dann werden Sie nicht definiertes Verhalten aufrufen, weil die Lebensdauer des referent (das Objekt x) beendet haben wird (x zerstört werden, wenn die Funktion zurückgibt, weil es eine automatische Variable) ist:

std::vector<int>& vec = test_function(); // undefined 
std::vector<int> vec = test_function(); // undefined 
+0

Wenn die Struktur, auf die verwiesen wird, nur eine Menge POD (keine Zeiger) oder ein Primitiv ist, wenn der normale Stapelrahmen gehalten wird, und Sie den Wert kopieren (nicht einen Verweis darauf halten, also Ihre Sekunde) Beispiel hier), der ursprüngliche lokale Wert ist unmittelbar nach der Rückkehr in Ordnung ('mov esp, ebp; pop ebp;' lokaler Stapelrahmen ist ungestört). Destruktoren werden jedoch aufgerufen, und die Daten können manipuliert/geändert werden. Dies ist der falsche Weg, um dies zu tun und zu prognostizieren, was passieren wird, auch wenn es an einem Ort genau zu erraten ist, ist es nicht tragbar. –

+0

@jMerliN: Auch bei einem POD-Objekt sind die Ergebnisse formal undefiniert. Die Lebensdauer eines POD endet, wenn seine Speicherdauer endet; Für eine lokale Variable ist dies der Punkt, an dem die Funktion zurückgibt. Die Verwendung eines Objekts nach dem Ende seiner Lebensdauer führt zu undefiniertem Verhalten. Funktioniert das bei POD-Objekten in der Praxis? Vielleicht, aber wie Sie sagen, ist es nicht das Verhalten, auf das man sich verlassen sollte. –

+0

Es sollte definitiv nicht darauf geachtet werden, wenn Multithreading Standard wird, da der Speicherort des Stapelrahmens bereits von einem anderen Thread wiederverwendet wurde (Hinweis: Der Standard definiert nicht, wie der Stack oder Heap implementiert wird). –

0

Sie können einen Verweis auf eine lokale Variable aus dem gleichen Grund nicht zurückgeben, aus dem Sie kein poi zurückgeben können nter zu einer lokalen Variablen, da bei der Rückkehr von der Funktion diese lokalen Variablen freigegeben werden und daher die Referenz oder der Zeiger ungültig wird.

2

Ja, es ist gültig, aber wenn Sie versuchen, den zurückgegebenen Wert zu verwenden, erhalten Sie undefiniertes Verhalten.