Referenz auf temporäres Objekt in Funktion - Während des Funktionsaufruf-Ausdrucks auch nicht mehr gültig?
-
Hi!
Ich frage mich, warum das nicht will:
set<int> values; struct TestStruct { vector<set<int>::iterator> entries; string remaining; }; // Wenn ich TestStruct nicht als Referenz zurückgebe, funktioniert es... TestStruct& GetEntries() { TestStruct testStruct; for(set<int>::iterator it = values.begin(); it != values.end(); ++it) testStruct.entries.push_back(it); testStruct.remaining = "test"; return testStruct; } int main() { values.insert(4); values.insert(7); values.insert(51); if(GetEntries().entries.empty()) cout << "LEER =(" << endl; }Die temporäre "testStruct" sollte doch während dem Funktionsaufruf-Ausdruck gültig bleiben? Gibt mir aber "LEER =(" aus (Im Releasebuild crasht es), außer wenn ich eine Kopie der Struktur zurückgebe.

-
Ganz einfach: testStruct geht den Bach runter, sobald die Funktion GetEntries zu Ende ist, also insbesondere, bevor der Ausdruck, in dem du GetEntries verwendest, auf den Rückgabewert zugreifen kann. Damit greift der Ausdruck über die Referenz dann auf das tote Objekt zu -> BOOM.
Eigentlich sollte dich der Compiler aber auch warnen, wenn du lokale Objekte per Referenz zurückgibst. (Benutzt du die passenden Compiler-Flags?)
Felix
-
ich weiss nicht wie ihr es schafft immer solche codes zusammenzufrickeln und euch dann noch wundert wenn sie nicht funzen, obwohl es 100 compiler warnings gibt und kein buch der welt solchen code anrät. ich seh es jeden tag in diesem forum genau diese frage. pointer auf irgendwelche lokalen variablen und dann die frage wieso geht das nicht? jeden tag.
vielleicht sollte man einen neuen Knopf im forum einführen, der einen fertigen antwort text für diese frage ins antwort feld einfügt oder so.
-
Die temporäre "testStruct"
...ist nicht temporär, sondern "auto", und als solche weg, sobald die Funktion endet.
Wenn du eine Kopie zurückgeben würdest, dann wäre diese Kopie temporär, und alles wäre gut.Ansonsten das was "häh" geschrieben hat.
-
Hmm, stimmt, ich bekomme ein warning.
ABER: Ist es nicht so, dass wenn man ein temporäres Objekt an eine Referenz bindet, die Lebensdauer des Objekts erweitert wird, und zwar dann der Lebensdauer der Referenz entspricht?
So meine ich es mal gelesen zu haben.

-
Auf dem Stack angelegte Sachen noch nach dem Rücksprung zu haben, wäre sehr aufwendig, weil die Rücksprungadresse auch auf dem Stack liegt und folglich vor dem Rücksprung, alles andere vom Stack muss.
-
Wann gilt dann diese Regel, falls sie überhaupt gilt (Lebensdauer eines temp. (btw. definition temp.?) Objekts = Lebensdauer der Referenz).
Und wenn ich halt eine Kopie zurückgeben, wäre dann das legal:
TestStruct& testStruct = GetEntries(); if(testStruct.entries.empty()) cout << "LEER =(" << endl;Ist dann jedenfalls nicht leer und crasht nicht im Release (Ich weiß, kann Glückssache sein).

-
Die Regel gilt, wenn man temporäre Objekte hat. Du hast da aber kein temporäres Objekt. Die Verlängerungsregel gilt übrigens nur für Referenzen, die 1. auf dem Stack liegen und 2.) auf ein konsstantes Objekte verweisen. z.B. so:
std::string const& ref = std::string("Hallo") + "Welt!";