2016-05-17 6 views
1

Kann mir jemand die 5. Zeile der Ausgabe erklären? Ich verstehe nicht, warum das MyClass Objekt b nicht erhaltenes Objekt c von func zugewiesen bekommen.Warum bekomme ich in diesem Code keine Rückgabewertoptimierung?

class MyClass 
{ 
public: 
    int x; 
    std::string s; 

    MyClass(const MyClass &other); 
    MyClass(); 
    void output(); 
}; 

MyClass::MyClass(const MyClass &other): x(2), s("s?") { } 
MyClass::MyClass() : x(1), s("s1") { } 

void MyClass::output() { cout << x << " " << s << endl; } 

MyClass func(MyClass c) //MyClass c = Myclass(a) 
{ 
    cout << "2. in func: "; c.output(); 
    c.s = "s2"; 
    cout << "3. in func: "; c.output(); 
    return c; 
} 

int main() 
{ 
    MyClass a; 
    cout << "1. "; a.output(); 
    MyClass b = func(a); 
    cout << "4. "; a.output(); 
    cout << "5. "; b.output(); 
} 

Die Ausgabe lautet:

1. 1 s1 
2. in func: 2 s? 
3. in func: 2 s2 
4. 1 s1 
5. 2 s? 

Ich verstehe, wo 1-4 aus tun Linien kommen, aber ich bekomme am Ende nicht, warum hat die MyClass b.s einen Wert von s? nicht die s2 . Liegt es daran, dass das Objekt const innerhalb des Bereichs func erstellt wurde?

EDIT: Ich weiß, dass der Kopierkonstruktor aufgerufen wird, wenn MyClass c Objekt innerhalb des func Umfang initialisiert wird, aber wie das zurückgegebene Objekt zugewiesen ist nicht auf b?

+0

es nicht s2 ist, weil 'MyClass b = func (a);' den Copykonstruktor 'b' für Anrufe, die initialisiert das string-Mitglied zu 's?' –

+2

Ich denke, Sie müssen möglicherweise klären, warum Sie von der Ausgabe überrascht sind. Ihre Frage ist subtiler, als Sie wahrscheinlich wissen, und keine der Antworten hat das aufgegriffen.Tipp: Ein alternativer Titel könnte lauten: "Warum bekomme ich in diesem Code keine * Rückgabewertoptimierung *?" – juanchopanza

+0

@juanchopanza das ist fertig, danke –

Antwort

2

Warum bekomme ich in diesem Code keine Rückgabewertoptimierung?

Der Grund ist, dass Ihre Funktion c zurückgibt, was ein Parameter ist. Obwohl es ein Wert und daher ein lokales Objekt in der Funktion ist, ist dies einer der Fälle, in denen (in diesem Fall namens Rückgabewertoptimierung, oder NRVO) vom C++ - Standard nicht zugelassen ist. Wenn Sie eine lokale Kopie von c zu schaffen, würde RVO erlaubt sein:

MyClass func(MyClass c) //MyClass c = Myclass(a) 
{ 
    MyClass d = c; 
    cout << "2. in func: "; d.output(); 
    d.s = "s2"; 
    cout << "3. in func: "; d.output(); 
    return d; 
} 

Mit diesen Änderungen, erhalte ich die folgend eine aktuelle Klirren ++ verwenden:

  1. 1 s1
  2. in Funktion: 2 s?
  3. in func: 2 s2
  4. 1 s1
  5. 2 s2
3
MyClass b = func(a); 

Diese Linie wird den Kopierkonstruktor von MyClass rufen b von a zu erstellen. Obwohl es eine = hat, tut es nicht rufen Sie den Zuweisungsoperator; Das Objekt wurde noch nicht erstellt, also gibt es nichts zuzuordnen.

Ein Objekt muss nicht const sein, um an eine const T& zu binden, sogar Provisorien können an sie binden.

+0

Also, was passiert mit dem Objekt, das vom 'func' zurückgegeben wird? –

+0

@MaTi Es ist am Ende dieses vollen Ausdrucks zerstört. – TartanLlama

+0

@Ma Ti Es wird zerstört, versuche deinen benutzerdefinierten Destruktor zu erstellen, um zu sehen, was passiert. – PcAF

0

Sie geben eine lokale Variable c in func zurück. Es wird eine Kopie erstellt, um in b kopiert zu werden. Ihr Kopierkonstruktor spezifiziert s = "s?" so wird es gesetzt.

+0

also wird es am Anfang und am Ende der Funktion "Kopie konstruiert"? –

+0

ja. Einmal an die Funktion übergeben und einmal zurückgegeben werden. – SurDin

Verwandte Themen