[gelöst] Warum läuft in diesem Code kein Fehler durch die Rückgabe einer lokalen Funktionsvariablen auf?



  • Ich habe mal folgenden Code ausgeführt:

    #include <iostream>
    #include <vector>
    
    using namespace std;
     
    vector<int> doubleValues (const vector<int>&);
     
    int main()
    {
        vector<int> v;
        for ( int i = 0; i < 100; i++ )
        {
            v.push_back( i );
        }
        v = doubleValues( v );
    }
    
    
    vector<int> doubleValues (const vector<int>& v)
    {
        vector<int> new_values;
        new_values.reserve(v.size());
        for (auto itr = v.begin(), end_itr = v.end(); itr != end_itr; ++itr )
        {
            new_values.push_back( 2 * *itr );
        }
        return new_values;
    }
    

    Die Funktionsvariable new_values wird hier an den Aufrufer zurück gegeben. Als ich das gelesen habe, wäre ich jede Wette eingegangen, dass das zu einem Fehler führt. Kann mir jemand sagen, warum das hier klappt? Wird diese Funktion verlassen, wird dann nicht auch new_values vom Stack geräumt, wodurch v im Aufrufer auf einen nicht mehr gültiges Stück Speicher zeigt?

    Gruß
    Kai



  • Weil du eine Kopie zurück gibst. (bzw. Aktuell wahrscheinlich gemoved wird). Probleme würdest du bekommen, wenn du ein Pointer auf den Vektor zurück geben würdest.



  • Hallo und vielen Dank für die schnelle und auch einleuchtende Antwort. Habe mich da vom Typ der Variablen verwirren lassen. Dann wäre dieser Code aber doch auch recht unperformant, wenn der gesamte Inhalt von dem einen in den anderen Vector kopiert wird.

    Viele Grüße
    Kai



  • Ja, theoretisch schon. Aber erstens würde hier der Vektor nicht kopiert, sondern verschoben (über den Move-Konstruktor), jedenfalls ab C++11. Das heißt, es passiert zwar was, aber es werden dabei nur ein paar Zeiger umgebogen, es wird nicht der ganze Inhalt des Vektors kopiert.

    Und zweitens kommt hier in diesem Fall NRVO (Named Return Value Optimization) zur Anwendung, das heißt, es wird überhaupt keine Kopie (oder Move) ausgeführt, weil das zurückgegebene Objekt direkt im Stackframe des Aufrufers konstruiert wird. Es gibt daher keinen Grund, sich Sorgen zu machen.



  • Und mal wieder was dazu gelernt.

    Vielen Dank


Log in to reply