To move or not to move



  • vector<string> stuff;
    {
    	string s = getStuff();
    	if (s.size())
    		stuff.push_back(move(s));
    }
    

    Sollte ich hier das move weglassen, weil der Compiler s selbst als Temporary erkennt?
    Es hieß mal irgendwo, dass

    return move(value);
    

    ineffizienter als

    return value;
    

    bei lokalen Variablen ist.



  • In deinem Beispielcode steht kein return. Warum sollte dein "es hiess mal" also dort greifen. Desweiteren sollte std::move nur den Typ umwandeln, d.h. es ist eine nop und sorgt nur dafuer, dass die "richtige" ueberladung ausgewaehlt wird. Keine Ahnung, ob es unter http://channel9.msdn.com/Events/GoingNative/2013/Don-t-Help-the-Compiler faellt.



  • nwp3 schrieb:

    Sollte ich hier das move weglassen, weil der Compiler s selbst als Temporary erkennt?

    Selbst wenn der Compiler so schlau sein sollte, dass er das erkennt, darf er hier kein move automatisch verwenden -- zumindest nicht in einer "as-if"-Regel-verletzenden Weise. Deine Verwendung von std::move ist hier also genau richtig und vordbildlich.

    Die einzige Stelle, bei der ein Compiler ein Lvalue als Rvalue behandeln darf, ist beim return eines funktionslokalen Objekts.

    nwp3 schrieb:

    Es hieß mal irgendwo, dass

    return move(value);
    

    ineffizienter als

    return value;
    

    bei lokalen Variablen ist.

    Genau. Du hebelst nämlich durch diese Verwendung von move die NRVO-Optimierung aus, die ein Compiler hier sonst anwenden dürfte (und typischerweise auch tut). NRVO ist noch günstiger als eine Move-Konstruktion. Mit std::move würdest du hier mindestens eine Move-Konstruktion bekommen, weil die Copy-Elision-Regel nicht mehr greifen kann. Das liegt daran, dass std::move etwas mehr als ein Cast ist: Es ist ein Funktionsaufruf -- auch wenn dieser geinlined werden kann und die Funktion sonst nichts besonderes macht.



  • krümelkacker schrieb:

    ...

    Vielen Dank!




Anmelden zum Antworten