rvalue referenzen



  • ich hab mal einen vortrag gesehen von scott meyers, wo er sagt, dass es fast immer falsch ist, wenn man in einer funktion eine rvalue referenz hat und diese nicht mit std::move umschliesst. wie sieht das hier in meinem fall aus?

    bool is_ok(std::string const& str)
    {
        return true;
    }
    void add_str(std::string&& str)
    {
        if(!is_ok(str)) // kein std::move(str)
        {
            // gibbet haue
        }
    }
    

    is_ok liest lediglich vom string und entscheidet anhand dessen inhalts, ob er geeignet ist. muss ich hier moven oder kann ich hier getrost gegen diese faustregel verstossen?

    lg



  • Ich weiß zwar nicht welchen Vortrag du meinst aber so hat Scott Meyers das bestimmt nicht gemeint. In deinem Beispiel würde man das std::move natürlich weglassen, schließlich verändert die Funktion is_ok das Objekt nicht und nimmt auch gar nicht (explizit) eine rvalue Referenz. Vermutlich kommt dann in dem if noch irgendwas das den string verändert. Da brauchst du dann möglicherweise ein std::move .



  • sebi707 schrieb:

    Ich weiß zwar nicht welchen Vortrag du meinst aber so hat Scott Meyers das bestimmt nicht gemeint. In deinem Beispiel würde man das std::move natürlich weglassen, schließlich verändert die Funktion is_ok das Objekt nicht und nimmt auch gar nicht (explizit) eine rvalue Referenz. Vermutlich kommt dann in dem if noch irgendwas das den string verändert. Da brauchst du dann möglicherweise ein std::move .

    ok, danke für die auskunft.



  • Ich vermute dass Scott gemeint hat: Es ist fast-immer Unsinn wenn man eine Funktion hat die nen R-Value Parameter hat und diesen nirgends mit std::move umschliesst.
    Das heisst nicht dass man überall std::move verwenden muss/sollte.
    Im Gegenteil: es wäre in vielen Funktionen in denen der Parameter mehrmals referenziert wird Unsinn überall std::move zu verwenden.
    (Es dürfen natürlich mehrere std::move vorkommen, so lange sie sich in unterschiedlichen Codepfaden befinden von denen immer nur max. einer durchlaufen wird.)

    Erklärung:

    R-Value Parameter heisst: Ich will das Ding möglicherweise "konsumieren" (im Sinne von "aufbrauchen", also "move from" halt). Wenn die Funktion aber nirgends std::move schreibt, dann wird sie den Wert normalerweise auch nirgends "konsumieren". Dann wäre der R-Value Parameter sinnlos und man könnte genau so gut ne normale Referenz nehmen.

    Und std::move heisst: Du darfst das hier und jetzt konsumieren. Mehrmals std::move ist daher auch Unsinn, denn man kann das Ding ja schliesslich nur 1x konsumieren (aufbrauchen).



  • hustbaer schrieb:

    Ich vermute dass Scott gemeint hat: Es ist fast-immer Unsinn wenn man eine Funktion hat die nen R-Value Parameter hat und diesen nirgends mit std::move umschliesst.
    Das heisst nicht dass man überall std::move verwenden muss/sollte.
    Im Gegenteil: es wäre in vielen Funktionen in denen der Parameter mehrmals referenziert wird Unsinn überall std::move zu verwenden.
    (Es dürfen natürlich mehrere std::move vorkommen, so lange sie sich in unterschiedlichen Codepfaden befinden von denen immer nur max. einer durchlaufen wird.)

    Erklärung:

    R-Value Parameter heisst: Ich will das Ding möglicherweise "konsumieren" (im Sinne von "aufbrauchen", also "move from" halt). Wenn die Funktion aber nirgends std::move schreibt, dann wird sie den Wert normalerweise auch nirgends "konsumieren". Dann wäre der R-Value Parameter sinnlos und man könnte genau so gut ne normale Referenz nehmen.

    Und std::move heisst: Du darfst das hier und jetzt konsumieren. Mehrmals std::move ist daher auch Unsinn, denn man kann das Ding ja schliesslich nur 1x konsumieren (aufbrauchen).

    hallo hustbaer

    danke für die auskunft. ja, das mag gut sein, dass scott das gemeint hat. was mich einfach ein wenig verwirrt hat, war, dass ich std::string&& (rval) implizit in einen std::string const& (lval) konvertieren kann. oder ist das nur, weil man auch sonst ab und zu rvals an const& binden kann wie in int const& foo = 42; ? heisst das dafür, dass das nicht ginge, wäre die signatur bool is_ok(std::string&) ?

    lg



  • heisst das dafür, dass das nicht ginge, wäre die signatur bool is_ok(std::string&)?

    Nein, auch das geht.

    rval hat ja jetzt einen Namen, wird also als LValue behandelt. Genau aus dem Grund braucht man ja std::move , um wieder ne RValue draus zu machen.



  • verstehe mit dem neuen Standard auch gar nicht mehr so richtig die Argument übergabe bei funktionen und methoden.

    Früher hiess es, bei funktionen, die read-onliny sind und bei denen das Argument recht groß ist, wie zB große Ojjekte, solle man ne const ref verwenden. Gilt das immer noch oder sollte man pass by value verwenden und auf die neue Optimierung der compiler hoffen?



  • Das gilt immer noch. Eine nette Tabelle von Herb Sutter gibts [url=https://github.com/CppCon/CppCon2014/blob/master/Presentations/Back%20to%20the%20Basics!%20Essentials%20of%20Modern%20C%2B%2B%20Style/Back%20to%20the%20Basics!%20Essentials%20of%20Modern%20C%2B%2B%20Style%20-%20Herb%20Sutter%20-%20CppCon%202014.pdf]hier[/url] Seite 24 oben (ich hoffe der Link ist gleich nicht kaputt). Bei read-only ist und war const Reference immer schon das Richtige. Interessant sind die anderen Fälle aber auch dort hat sich nicht viel geändert zu den bisherigen Empfehlungen.

    Das Value Semantik statt Referenzen praktischer sind trifft auf Rückgabewerte zu. Früher hat man oft eine Referenz oder Pointer auf eine Klasse an eine Funktion gegeben und die Funktion hat die Klasse dann mit Werten gefüllt. Seitdem fast jeder Compiler RVO unterstützt und der Standard wenigstens ein Move garantiert wenn RVO nicht stattfindet macht Return by Value wieder sinnvoll.





  • bin ich der Einzige, bei dem Github total rumspackt?

    Beim öffnen der Seite in Chrome stürtzt mir der gesamte Browser ab, und das seit Tagen


Anmelden zum Antworten