move assignment - frage



  • Angenommen ich habe einen operator wie diesen:

    Myt& operator = (Myt&& o)
    {   // move assignment
    MyPos = std::move(o.MyPos);
    MyTextures = std::move(o.MyTextures);
    return (*this);
    }
    
    Myt& operator = (Myt&& o)
    {   // move assignment
    MyPos = o.MyPos;
    MyTextures = o.MyTextures;
    return (*this);
    }
    

    sollte man das so machen wie ich dasss man jedes attribut mit einem aufruf von
    std::move() übergibt oder einfach wie in der zweiten variante?



  • Das dürfte wohl von den Datentypen der Member abhängen.



  • was du meinst ist warscheinlich dass man das bei listen strings und so machen sollte, bei basistypen wie bool oder int aber nicht?
    frage ist wo man die grenze zieht 😕
    gibt ja auch sachen wie std::pair<int,int> oder std::shared_ptr<int>. da wäre ich mir nicht sicher was ich machen sollte



  • move, wenn Klasse mit move Constructor.



  • Ich würde in jedem Fall std::move nehmen. Ansonsten wird in dem fall nichts gemoved. Bei Typen die kein Move unterstützen, schadet es zumindest nicht. Man sollte sich aber auch vorher überlegen, ob die Default-implementierung des Operators nicht ausreichend ist. Das sollte der Fall sein, falls keine Zeiger manuell umgebogen werden müssen.



  • Wenn move assignment für den Datentyp implementiert ist, dürfte std::move wohl sinnvoll sein. Bei unique_ptr sollte die andere Version nicht funktionieren. Bei normalen Pointern muss in der Regel die Quelle auf nullptr gesetzt werden, da würde keine deiner Version ausreichen.



  • okay, ich denke ich habs verstanden danke 👍

    welche operatoren, konstruktoren werden eigendlich automatisch implementiert?
    default constructor,
    copy constructor,
    ...



  • Um es noch mal zu präzisieren: wenn der Operator wirklich genau so aussieht wie in deinem Beispiel sollte das reichen:

    Myt& operator = (Myt&& o) = default;
    


  • Myt& operator = (Myt&& o) = default;

    das geht? 😮
    kannst du das mal kurz genauer erklären und sagen wo das überall geht? hab sowas noch nie gesehen 😃



  • gamer8o4 schrieb:

    okay, ich denke ich habs verstanden danke 👍

    welche operatoren, konstruktoren werden eigendlich automatisch implementiert?
    default constructor,
    copy constructor,
    ...

    zusätzlich gibt es noch die auto Implementierungen:

    destructor
    copy assignment
    operator new
    sowie
    move constructor
    und move asignment

    Wobei ich nicht sicher bin, wann die letzten beiden wirklich implizit angelegt werden. Das wäre wirklich interessant zu wissen.



  • gamer8o4 schrieb:

    Myt& operator = (Myt&& o) = default;

    das geht? 😮
    kannst du das mal kurz genauer erklären und sagen wo das überall geht? hab sowas noch nie gesehen 😃

    Ist neu mit C++11 Das geht bei allen Operatoren die der Compiler automatisch generieren kann, also alle dir wir beide aufgezählt haben.

    Edit: Siehe auch http://en.wikipedia.org/wiki/C++11#Explicitly_defaulted_and_deleted_special_member_functions



  • Vielen dank 👍


  • Mod

    Das geht bei allen Operatoren die der Compiler automatisch generieren kann, also alle dir wir beide aufgezählt haben.

    Das geht überhaupt mit allen deklarierbaren Funktionen, auch welche, die keine Memberfunktionen sind.

    void foo(int) = delete;
    void foo(short){}
    void foo(double) {}
    void foo(float) = delete;
    

  • Mod

    gamer8o4 schrieb:

    Angenommen ich habe einen operator wie diesen:

    Myt& operator = (Myt&& o)
    {   // move assignment
    MyPos = std::move(o.MyPos);
    MyTextures = std::move(o.MyTextures);
    return (*this);
    }
    
    Myt& operator = (Myt&& o)
    {   // move assignment
    MyPos = o.MyPos;
    MyTextures = o.MyTextures;
    return (*this);
    }
    

    sollte man das so machen wie ich dasss man jedes attribut mit einem aufruf von
    std::move() übergibt oder einfach wie in der zweiten variante?

    Bei der 2. Variante wird kopiert. o ist ein lvalue, und damit sind auch Zugriffe auf (Daten-)Member von o lvalues.
    Man könnte auch

    Myt& operator = (Myt&& o)
    {   // move assignment
    MyPos = std::move(o).MyPos;
    MyTextures = std::move(o).MyTextures;
    return (*this);
    }
    

    schreiben, dass ist aber eher ungewöhnlich (Unterschiede ergeben sich, wenn die Member selbst Referenzen sind). Nat. sollte immer die Default-Implementation verwendet werden, wenn die Semantik stimmt.



  • hier die weitere Lektüre 😉

    12.8 Copying and moving class objects

    7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. Thus, for the class definition
    struct X {
    X(const X&, int);
    };
    a copy constructor is implicitly-declared. If the user-declared constructor is later defined as
    X::X(const X& x, int i =0) { / ... / }
    then any use of X’s copy constructor is ill-formed because of the ambiguity; no diagnostic is required.

    8 The implicitly-declared copy constructor for a class X will have the form
    X::X(const X&)
    if
    — each direct or virtual base class B of X has a copy constructor whose first parameter is of type const B& or const volatile B&, and
    — for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy constructor whose first parameter is of type const M& or const volatile M&.[119]
    Otherwise, the implicitly-declared copy constructor will have the form
    X::X(X&)

    1. This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see C.1.9.

    9 If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
    — X does not have a user-declared copy constructor,
    — X does not have a user-declared copy assignment operator,
    — X does not have a user-declared move assignment operator,
    — X does not have a user-declared destructor, and
    — the move constructor would not be implicitly defined as deleted.
    [ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that otherwise would have invoked the move constructor may instead invoke a copy constructor. —end note ]

    10 The implicitly-declared move constructor for class X will have the form
    X::X(X&&)

    11 An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:
    — a variant member with a non-trivial corresponding constructor and X is a union-like class,
    — a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
    — a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
    — any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
    — for the copy constructor, a non-static data member of rvalue reference type, or
    — for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.

    18 If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor. The implicitlydeclared copy assignment operator for a class X will have the form
    X& X::operator=(const X&)
    if
    — each direct base class B of X has a copy assignment operator whose parameter is of type const B&, const volatile B& or B, and
    — for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose parameter is of type const M&, const volatile M& or M. [122]
    Otherwise, the implicitly-declared copy assignment operator will have the form
    X& X::operator=(X&)

    1. This implies that the reference parameter of the implicitly-declared copy assignment operator cannot bind to a volatile lvalue; see C.1.9.

    19 A user-declared move assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X&&, const X&&, volatile X&&, or const volatile X&&. [ Note: An overloaded assignment operator must be declared to have only one parameter; see 13.5.3. —end note ] [ Note: More than one form of move assignment operator may be declared for a class. —end note ]

    20 If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly declared as defaulted if and only if
    — X does not have a user-declared copy constructor,
    — X does not have a user-declared move constructor,
    — X does not have a user-declared copy assignment operator,
    — X does not have a user-declared destructor, and
    — the move assignment operator would not be implicitly defined as deleted.

    21 The implicitly-declared move assignment operator for a class X will have the form
    X& X::operator=(X&&);

    23 A defaulted copy/move assignment operator for class X is defined as deleted if X has:
    — a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or
    — a non-static data member of const non-class type (or array thereof), or
    — a non-static data member of reference type, or
    — a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator, or
    — a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator, or
    — for the move assignment operator, a non-static data member or direct base class with a type that does not have a move assignment operator and is not trivially copyable, or any direct or indirect virtual base class.



  • Arcoth schrieb:

    Das geht bei allen Operatoren die der Compiler automatisch generieren kann, also alle dir wir beide aufgezählt haben.

    Das geht überhaupt mit allen deklarierbaren Funktionen, auch welche, die keine Memberfunktionen sind.

    void foo(int) = delete;
    void foo(short){}
    void foo(double) {}
    void foo(float) = delete;
    

    Das delete schon, ich bezog mich aber auf default.


  • Mod

    Ich bin Blind, man verzeihe mir 🙂


Log in to reply