C++11: move schneller als const Referenz?



  • Ich habe in einem Video von der Native2013 gesehen, dass der Code aus My2ndClass schneller sein soll als der von MyClass. Kann mir einer erklären warum?

    #include <iostream>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    class MyClass {
    public:
    	MyClass(const string &name)
    	:
    	name(name) {}
    
    private:
    	string name;
    };
    
    class My2ndClass {
    public:
    	My2ndClass(string name)
    	:
    	name(move(name)) {}
    
    private:
    	string name;
    };
    
    int main() {
    	string s{"bla"};
    	MyClass my{s};
    	My2ndClass my2{s};
    
    	return 0;
    }
    


  • edit: hier stand vermutlich quatsch



  • Kann ich auch nicht nachvollziehen.
    So sehe ich das:

    MyClass: copy-ctor.
    My2ndClass: copy-ctor, move-ctor.

    Möglicherweiße hat's was mit Optimisierung zu tun.
    ~Edit à la Vollständigkeit:~
    Möglicherweiße optimiert der Compiler den copy-ctor von My2ndClass weg, wodurch nur der move-ctor übrig bleibt.



  • Singender Holzkübel schrieb:

    Kann ich auch nicht nachvollziehen.
    So sehe ich das:

    MyClass: copy-ctor.
    My2ndClass: copy-ctor, move-ctor.

    Bei dem gegebenen Beispiel ist das richtig ja, aber bei folgender main:

    int main() {
        MyClass my{"bla"};
        My2ndClass my2("bla"};
    
        return 0;
    }
    

    MyClass: copy-ctor.
    My2ndClass: move-ctor, move-ctor.
    Insbesondere da move für std::string nur ein paar Pointerzuweisungen sein sollten, ist das ein Vorteil.
    Sutter bezeichnet dieses Idiom allerdings als Antipattern für alle Funktionen außer Konstruktoren (siehe hier auf Stackoverflow: http://stackoverflow.com/questions/26261007/why-is-value-taking-setter-member-functions-not-recommended-in-herb-sutters-cpp).



  • Diese Optimierung wird automatisch von clang-modernize oder wie das heißt durch geführt und das Tool macht aus der Klasse MyClass dann die My2ndClass. Er sprach in dem Video irgendwas davon dass Allocation und Syncronisation bei der 2ndClass wegfalle und es deswegen schneller ist.



  • @ModernCpp
    Ich glaube den meisten hier ist klar warum das -- potentiell -- schneller ist 😉

    Nur dass es in genau der vom OP gezeigten Variante nicht funktioniert. Weil "s" nicht geopfert werden darf. Weil "s" ne LValue ist.

    In der von Nathan gezeigten Variante ist es aber schneller. Weil eben bei My2ndClass das temporäre String Objekt welches erstellt wird um den ctor mit nem std::string aufrufen zu können geopfert werden kann. Weil's halt - im Gegensatz zu "s" - ne RValue ist.


Log in to reply