2010-04-02 36 views
10

Ist dies der richtige Weg, um ein Objekt von einer Funktion zurückzugeben?Rückgabe eines lokalen Objekts aus einer Funktion

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

displayCar(getCar("Honda", 1999)); 

Ich bekomme einen Fehler, "die Adresse von temporären". Sollte ich diesen Weg verwenden:

Car &getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

Antwort

23

getCar ein Car von Wert zurückgibt, was richtig ist.

Sie können diesen Rückgabewert, der ein temporäres Objekt ist, nicht an displayCar übergeben, da displayCar eine Car& übernimmt. Sie können eine temporäre nicht an eine nicht konstante Referenz binden. Sie sollten displayCar ändern, um eine konstante Referenz zu nehmen:

void displayCar(const Car& car) { } 

Oder Sie die temporäre in einer lokalen Variablen speichern kann:

Car c = getCar("Honda", 1999); 
displayCar(c); 

Aber es ist besser displayCar nehmen eine konstante Referenz zu haben, da es doesn Ändere das Objekt nicht.

Geben Sie nicht einen Verweis auf die lokale Variable Car zurück.

+0

Sie können auch das temporäre speichern, ohne den Kopierkonstruktor aufzurufen (was in 'Car c = getCar (...)' geschieht, indem Sie einen Verweis auf const verwenden: 'const Car & c = getCar (...)', wenn Sie nicht "0" müssen später Änderungen durch "c" vornehmen. –

4

Es ist nicht sicher, die Referenz einer lokalen Variablen von einer Funktion zurückzugeben.

Also ja das ist richtig:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 
+0

Hmm, ich brauche so etwas wie eine Factory-Funktion, die ein Objekt erstellen und es zurückgeben wird. – pocoa

+1

Viele (die meisten?) Compiler optimieren 'return Car (Modell, Jahr)', so dass keine zusätzliche Kopie gemacht werden muss, so würde ich die explizite lokale Variable loswerden. –

+0

@Steven: Viele (die meisten?) Compiler implementieren auch die benannte Rückgabewertoptimierung (NRVO), daher gibt es im Allgemeinen keinen Unterschied. –

8

Ihr Problem ist:

void displayCar(Car &car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

Sie eine konstante Referenz verwendet werden soll:

void displayCar(const Car & car) { 
    cout << car.getModel() << ", " << car.getYear() << endl; 
} 

Diese Funktion:

Car getCar(string model, int year) { 
    Car c(model, year); 
    return c; 
} 

ist OK, wie es steht, aber alle es tut ist was der Konstruktor tut, also ist es überflüssig. zurück, sondern als ein Referenz Wert Geben, das Richtige ist für diesen Typen der Funktion zu tun, jedoch sollte der Modellparameter durch konstante Referenz übergeben werden:

Car getCar(const string & model, int year) { 

In der Regel für Klassentypen wie string oder Car, sollte Ihre Standardauswahl für einen Parameter immer eine const-Referenz sein.

0

Noch besser:

Car getCar(string model, int year) { 
     return Car(model, year); 
} 
+0

Genau das, was ich mit "Kopieroperationen" in meiner Antwort gemeint habe. Obwohl dies zur Zeit die Standardlösung ist, ist es viel mehr eine teure Operation als nur eine Adresse zurückzugeben. – themoondothshine

+1

@themoondothshine : Die meisten Compiler (alles, was ich weiß) wird RVO hier durchführen, also ist es eine wirklich billige Operation. –

2

Ja, es ist definitiv nicht sicher eine Referenz oder einen Zeiger auf ein temporäres Objekt zurückzukehren. Wenn es abläuft (dh wenn die Funktion getCar beendet wird), bleibt ein technisches "Dangling Pointer" übrig.

Wenn Sie jedoch Kopiervorgänge für ein Objekt reduzieren möchten, sollten Sie C++ 0x "Move Semantics" auschecken. Es ist ein relativ neues Konzept, aber ich bin sicher, dass es bald genug Mainstream wird. GCC 4.4 aufwärts unterstützt C++ 0x (verwenden Sie die Compiler-Option -std=c++0x zur Aktivierung).

Verwandte Themen