2015-09-03 12 views
6

Es fiel mir gerade ein, dass operator+ & co auf this für rvalues ​​arbeiten kann; das heißt, eine Klasse gegeben C, dann ist es möglich, dies zu tun:Ist es sinnvoll, Operatoren mit Ref-Qualifier zu überladen, um Provisorien zu vermeiden?

class C { 
    // ... 
    C operator-(const C& rhs) const & { 
     C result = *this; 
     result -= rhs; 
     return result; 
    } 
    C&& operator-(const C& rhs) && { 
     *this -= rhs; 
     return std::move(*this); 
    } 
}; 

Diese Kopien durch einfaches Modifizieren temporäre Werte an Ort und Stelle verhindern würde.

Würde das so funktionieren, wie ich es erwarte? Ist es eine vernünftige Optimierung oder würde der Compiler genauso schnellen Code erstellen?

+0

Mit der ersten Version können Sie bereits Kopier-Ellision bekommen. Ich bin mir also nicht sicher, ob der zweite gebraucht wird (wenn es überhaupt funktioniert, fühle ich mich, als würde es dich in den Arsch beißen, aber ich könnte mich irren) – Borgleader

+0

Ja, ich habe das Gefühl, dass eine Kopie zu ähnlicher Leistung führen könnte. .. Aber ich sehe nicht, wie meine Version mich noch in den Arsch beißen könnte. (Ich bin mir aber nicht sicher, daher die Frage.) –

+0

Object Lebensdauer Probleme. 'C && c = C() - einige_C;' und 'c' baumelt. –

Antwort

5

Lassen Sie uns sagen, dass wir std::string nur wickeln und eine vereinfachte Version von operator+ tun:

struct C { 
    std::string val; 

    C&& operator+(const C& rhs) && { 
     val += rhs.val; 
     return std::move(*this); 
    } 

    std::string::iterator begin() { return val.begin(); } 
    std::string::iterator end() { return val.end(); } 
}; 

Damit das funktioniert gut:

for (char c : C{"hello"}) { .. } 

der Bereich-für-Expression wird die Lebensdauer des verlängern vorübergehend, also sind wir in Ordnung. Aber bedenken Sie:

for (char c : C{"hello"} + C{"goodbye"}) { .. } 

Wir haben effektiv:

auto&& __range = C{"hello"}.operator+(C{"goodbye"}); 

Hier wir keine temporäre auf eine Referenzbindung. Wir binden eine Referenz. Das Objekt wird nicht verlängert, weil ... es kein Objekt ist. Wir haben also eine freie Referenz und ein undefiniertes Verhalten. Dies wäre sehr überraschend für Benutzer, die diese Arbeit erwarten:

for (char c : std::string{"hello"} + std::string{"goodbye"}) { .. } 

Sie würden einen Wert zurückgeben haben:

C operator+(const C& rhs) && { 
    val += rhs.val; 
    return std::move(*this); 
} 

, das dieses Problem löst (wie jetzt wir temporäre Erweiterung haben), und wenn das Verschieben Ihrer Objekte billiger ist als das Kopieren, ist das ein Gewinn.

Verwandte Themen