move assignment operator überladen



  • Hi Leute

    ich habe noch ein kleines Verständnisproblem bezüglich der Überladung von move-assignment-operatoren.

    Folgende Konstruktion:

    class MyBase
    {
    public:
        MyBase( const std::string &dummy ) : Member1( dummy ) {}
        virtual ~MyBase() {}
    
        MyBase( const MyBase & ) = delete;
        MyBase &operator=( const MyBase & ) = delete;
    
        MyBase &operator=( MyBase &&rhs )
        {
            if ( this != &rhs )
                Member1 = std::move( rhs.Member1 );
            return *this;
        }
    
        inline const std::string &text1() const { return Member1; }
    
    private:
        std::string Member1 = "";
    };
    
    class MyDerivate : public MyBase
    {
    public:
        MyDerivate( const std::string &dummy1, const std::string &dummy2 ) : MyBase( dummy1 ), Member2( dummy2 ) {}
        virtual ~MyDerivate() {}
    
        MyDerivate( const MyDerivate & ) = delete;
        MyDerivate &operator=( const MyDerivate & ) = delete;
    
        MyDerivate &operator=( MyDerivate &&rhs )
        {
            if ( this != &rhs )
            {
                *this = MyBase::operator=( std::move( rhs ) ); // ????????
                Member2 = std::move( rhs.Member2 );
            }
            return *this;
        }
    
        inline const std::string &text2() const { return Member2; }
    
    private:
        std::string Member2 = "";
    };
    

    Ich habe eine Basisklasse, die einen move-assignment-operator definiert und entsprechend die eigenen Member moved.

    Darüberhinaus habe ich eine abgeleitete Klasse die auch diese operator definiert und die den move-assignment-operator ihrer Basisklasse aufrufen soll, bevor sie wiederum ihre eigenen Member moved.

    Aber genau diesen Aufruf des Move-Assignment-Operators der Basisklasse krieg ich nich auf die Reihe... Hab leider kein gutes C++-Buch am Start. Nur ein mittelmäßiges da die lieben Kollegen eine Englisch-Allergie haben. Move wird da auf 10 Seiten abgehandelt...

    Jemand sowas schonmal gemacht?

    gruß Tobi



  • Einfach nur

    MyBase::operator=( std::move( rhs ) );
    

    also "*this = " löschen (denn der Basisklassen-Operator führt ja schon die Move-Operation für alle Member aus).



  • Danke dir. Das mit dem *this ist mir auch gerade wie Schuppen von den Augen gefallen...

    Funzt 😉



  • Sollte in deinem Beispiel nicht

    MyBase &operator=( MyBase && ) = default;
    ...
    MyDerivate &operator=( MyDerivate && ) = default;
    

    ausreichen?

    std::string Member2 = "";
    

    std::string initialisiert sich im Defaultkonstruktor, da braucht man nicht eingreifen.



  • Guter Punkt. Grundsätzlich war es nur als Beispiel gedacht.

    Aber der Hinweis ist gut. Gibts denn eine Garantie, dass das mit default immer funktioniert und da nicht bei irgendeinem Member mal eine Deepcopy gemacht wird?



  • It0101 schrieb:

    Gibts denn eine Garantie, dass das mit default immer funktioniert und da nicht bei irgendeinem Member mal eine Deepcopy gemacht wird?

    Nein. Aber wenn du stumpf

    Member2 = std::move( rhs.Member2 );
    

    schreibst kann ja auch kopiert werden.



  • Also zumindest wenn der Move-Assignment-Operator explizit deleted ist, wirft der Compiler beim einem std::move-Aufruf einen Fehler.

    D.h. in dem Fall kann nicht versehentlich eine Kopieroperation vorgenommen werden.

    test.h|62|error: use of deleted function 'MyMemberWithoutMove& MyMemberWithoutMove::operator=(MyMemberWithoutMove&&)'|
    

    Da muss man schon einen Move-Operator aus Kopieroperationen bauen. Ich erwarte, dass zumindest die autogenerierten Default-Konstruktoren sauber sind.

    Was ja auch meine Frage war. 😉


Log in to reply