Ist die Rückgabe per Rvalue-Referenz effizienter?

Lesezeit: 4 Minuten

Ist die Ruckgabe per Rvalue Referenz effizienter
Neil G

zum Beispiel:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

1646967612 836 Ist die Ruckgabe per Rvalue Referenz effizienter
Johannes Schaub – litb

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

Dies gibt eine baumelnde Referenz zurück, genau wie im Fall der lvalue-Referenz. Nachdem die Funktion zurückkehrt, wird das temporäre Objekt zerstört. Sie sollten zurückkehren Beta_ab nach Wert, wie im Folgenden

Beta_ab
Beta::toAB() const {
    return Beta_ab(1, 1);
}

Jetzt bewegt es richtig ein Provisorium Beta_ab Objekt in den Rückgabewert der Funktion. Wenn der Compiler kann, vermeidet er die Verschiebung vollständig, indem er RVO (Return Value Optimization) verwendet. Jetzt können Sie Folgendes tun

Beta_ab ab = others.toAB();

Und es wird das Provisorische hineinziehen ab, oder machen Sie RVO, um das Verschieben oder Kopieren ganz zu unterlassen. Ich empfehle Ihnen zu lesen BoostCon09 Rvalue Referenzen 101 was die Sache erklärt und wie (N) RVO damit interagiert.


Ihr Fall, eine Rvalue-Referenz zurückzugeben, wäre bei anderen Gelegenheiten eine gute Idee. Stellen Sie sich vor, Sie haben eine getAB() Funktion, die Sie oft für ein Temporär aufrufen. Es ist nicht optimal, eine konstante lvalue-Referenz für temporäre Rvalues ​​zurückzugeben. Sie können es so implementieren

struct Beta {
  Beta_ab ab;
  Beta_ab const& getAB() const& { return ab; }
  Beta_ab && getAB() && { return move(ab); }
};

Beachten Sie, dass move in diesem Fall ist nicht optional, weil ab ist weder eine lokale Automatik noch ein temporärer Rvalue. Jetzt die Ref-Qualifizierer && sagt, dass die zweite Funktion für rvalue-Temporäre aufgerufen wird und die folgende Bewegung anstelle von Copy ausführt

Beta_ab ab = Beta().getAB();

  • Ich war immer davon ausgegangen, dass das Problem der baumelnden Referenzen automatisch verschwunden ist, wenn der Rückgabetyp eine R-Wert-Referenz war. Ich bin froh, dass ich das geklärt habe, bevor es mich gebissen hat. Stack-Smashing-Bugs sind scheiße.

    – geschickt_code

    15. Juli 2009 um 3:03 Uhr

  • 🙂 Wirklich, Rvalue-Referenzen sind “nur Referenzen”, wie Lvalue-Referenzen sind. sie kopieren oder speichern nichts.

    – Johannes Schaub – litb

    10. März 2010 um 2:17 Uhr

  • Was bedeutet die Konstante und der Qualifizierer für eine Member-Funktion mehr als eine einfache Konstante?

    – Galette

    11. April 2014 um 11:33 Uhr

  • +1-ed, aber defekter Link: BoostCon09 Rvalue Referenzen 101

    – Siu Ching Pong -Asuka Kenji-

    30. März 2015 um 0:45 Uhr


  • @galinette Das sind Ref-Qualifikanten.

    – Malcolm

    20. Oktober 2015 um 10:55 Uhr


Es kann effizienter sein, zum Beispiel in einem etwas anderen Kontext:

template <typename T>
T&& min_(T&& a, T &&b) {
    return std::move(a < b? a: b);
}

int main() {
   const std::string s = min_(std::string("A"), std::string("B"));
   fprintf(stderr, "min: %s\n", s.c_str());
   return 0;
}

Als interessante Beobachtung auf meiner Maschine clang++ -O3 generiert 54 Anweisungen für den obigen Code im Vergleich zu 62 Anweisungen für den regulären std::min. Allerdings mit -O0 Es generiert 518 Anweisungen für den obigen Code im Vergleich zu 481 für den regulären std::min.

  • Ich bin verwirrt von deiner Antwort. Hatte eine ähnliche (vielleicht) Version ausprobiert, war aber gescheitert: ideone.com/4GyUbZ Können Sie erklären, warum?

    – Deqing

    11. April 2018 um 0:25 Uhr

  • Sie haben den Verweis auf das temporäre Objekt in verwendet for(:) und Integrieren über freigegebene Objekte. Fix: ideone.com/tQVOal

    – Wunder.Mäuse

    11. April 2018 um 17:42 Uhr

  • Ist diese Antwort nicht eigentlich falsch? für Vorlagenparameter T ist T&& nicht eine R-Wert-Referenz, sondern eher eine universelle Referenz, und für diesen Fall sollten wir immer std::forward aufrufen, nicht std::beweg dich! Ganz zu schweigen davon, dass diese Antwort der am besten bewerteten oben direkt widerspricht.

    – xdavidliu

    3. November 2019 um 17:49 Uhr


  • @xdavidliu diese Antwort ist ein erfundenes Beispiel dafür, wie die Rückgabe von rvalue effizienter sein kann. std::move() wird nur als explizite Besetzung verwendet, um den Punkt klarer zu veranschaulichen. Es ist kein Code, den Sie kopieren und in Ihr Projekt einfügen würden. Es widerspricht nicht der am besten bewerteten Antwort, da innerhalb der Funktion ein temporäres Objekt erstellt wird. Hier ist das zurückgegebene Objekt eines der Argumente (temporäre Objekte werden als letzter Schritt bei der Auswertung des vollständigen Ausdrucks zerstört, der (lexikalisch) den Punkt enthält, an dem sie erstellt wurden).

    – Wunder.Mäuse

    15. April 2020 um 19:08 Uhr

  • @wonder.mice dann bitte T durch std::string ersetzen; Es besteht hier überhaupt keine Notwendigkeit, Vorlagen zu verwenden, und die Verwendung von T&& als R-Wert-Referenz ist nur ein schrecklicher Stil, der unnötigerweise Leute verwirrt, die neu in Bezug auf Vorlagen und R-Werte sind.

    – xdavidliu

    15. April 2020 um 19:14 Uhr

989680cookie-checkIst die Rückgabe per Rvalue-Referenz effizienter?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy