RVO-Frage

01/01/2015 - 13:41 von mirko | Report spam
Hallo,

ich verstehe nicht, warum return value optimization (RVO) nicht bei jeder Art von temporàrem Rückgabewert funktioniert. Im Beispiel, das ich versucht habe, knapp zu halten, verhalten sich alle Funktionsaufrufe wie erwartet, aber nicht der Aufruf von h4(). Da wird der Kopierkonstrutor 2-mal aufgerufen statt wie erwartet einmal:

#include<iostream>
#include<utility>

class A {
public:
explicit A(int w) : wert(w) {
std::cout << "A(int) aufgerufen";
}
A(const A& a) : wert(a.get()) {
std::cout << "A(const A&) aufgerufen";
}
A(A&& a) : wert(std::move(a.get())) {
std::cout << "A(A&&) aufgerufen";
}
A& operator=(const A&) = default;
A& operator=(A&&) = default;
int get() const { return wert; }
A& set(int w) { wert = w; return *this; }
private:
int wert;
};

inline A h3() { // temporary 1
return A(17);
}

inline A h4(const A& a) { // temporary 2: Wieso kein RVO?
return (A(a)).set(99);
}

inline A h5(const A& a) { // temporary: ok, move c'tor
return std::move((A(a)).set(42));
}


int main() {
A lvalue(5);
A a1 = h3();
std::cout << "h3() wert = " << a1.get() << "";
/* Ausgabe:
A(int) aufgerufen
A(int) aufgerufen
h3() wert = 17 */
int result = h4(lvalue).get();
std::cout << "h4(lvalue) wert = " << result << "";
/* Ausgabe:
A(const A&) aufgerufen
A(const A&) aufgerufen
h4(lvalue) wert = 99 */
result = h5(lvalue).get();
std::cout << "h5(lvalue) wert = " << result << "";
/* Ausgabe:
A(const A&) aufgerufen
A(A&&) aufgerufen
h5(lvalue) wert = 42 */
}

Hat jemand einen Tipp, warum h3() und h4() sich unterschiedlich bzgl. RVO verhalten?

mirko
 

Lesen sie die antworten

#1 mirko
01/01/2015 - 16:12 | Warnen spam
Am Donnerstag, 1. Januar 2015 15:20:04 UTC+1 schrieb mirko:
Hallo,

ich verstehe nicht, warum return value optimization (RVO) nicht bei jeder Art von temporàrem Rückgabewert funktioniert. Im Beispiel, das ich versucht habe, knapp zu halten, verhalten sich alle Funktionsaufrufe wie erwartet, aber nicht der Aufruf von h4(). Da wird der Kopierkonstrutor 2-mal aufgerufen statt wie erwartet einmal:

#include<iostream>
#include<utility>

class A {
public:
explicit A(int w) : wert(w) {
std::cout << "A(int) aufgerufen";
}
A(const A& a) : wert(a.get()) {
std::cout << "A(const A&) aufgerufen";
}
A(A&& a) : wert(std::move(a.get())) {
std::cout << "A(A&&) aufgerufen";
}
A& operator=(const A&) = default;
A& operator=(A&&) = default;
int get() const { return wert; }
A& set(int w) { wert = w; return *this; }
private:
int wert;
};

inline A h3() { // temporary 1
return A(17);
}

inline A h4(const A& a) { // temporary 2: Wieso kein RVO?
return (A(a)).set(99);
}

inline A h5(const A& a) { // temporary: ok, move c'tor
return std::move((A(a)).set(42));
}


int main() {
A lvalue(5);
A a1 = h3();
std::cout << "h3() wert = " << a1.get() << "";
/* Ausgabe:
A(int) aufgerufen
A(int) aufgerufen
h3() wert = 17 */
int result = h4(lvalue).get();
std::cout << "h4(lvalue) wert = " << result << "";
/* Ausgabe:
A(const A&) aufgerufen
A(const A&) aufgerufen
h4(lvalue) wert = 99 */
result = h5(lvalue).get();
std::cout << "h5(lvalue) wert = " << result << "";
/* Ausgabe:
A(const A&) aufgerufen
A(A&&) aufgerufen
h5(lvalue) wert = 42 */
}

Hat jemand einen Tipp, warum h3() und h4() sich unterschiedlich bzgl. RVO verhalten?

mirko



Sorry für die Umstànde. set() gibt eine REFERENZ zurück, kein Objekt. Deshalb findet RVO nicht statt
mirko

Ähnliche fragen