mercredi 5 février 2020

Implicit move vs copy operations and containment

I am struggling to understand implicit move operations when a class has a member whose move operations were not defined:

int main() {
    struct A // no move: move = copy
    {
        A() = default;
        A(const A&) {
            cout << "A'copy-ctor\n";
        };
        A& operator=(const A&) {
            cout << "A'copy-assign\n";
            return *this;
        }
    };

    struct B
    {
        B() = default;
        A a; // does this make B non-moveable?
        unique_ptr<int> upi;
        // B(B&&) noexcept = default;
        // B& operator=(B&&)noexcept = default;
    };

    A a;
    A a2 = std::move(a); // ok use copy ctor instead of move one
    a2 = std::move(a); // ok use move assignment instead of move one

    B b;
    B b2 = std::move(b); // why this works?
    b = std::move(b2); // and this works?
    // b = b2; // error: copy deleted because of non-copyable member upi

    cout << "\nDone!\n";
}

So what I see is A is a non-moveable class because of the definition of its copy control operations so it can only be copied and any attempt to move an object of this class, the corresponding copy operation is used instead.

Until here it is OK if i am correct. But B has a non-copy-able object upi which is a unique_ptr thus the copy operations are defined as deleted functions so we cannot copy objects of this class. But this class has a non-move-able object a thus i think that this class (B) is neither copy-able nor move-able. But why the initialization of b2 and the assignment of b works fine? What happens exactly?

B b2 = std::move(b); // ok?!

Why the line above invokes the copy constructor of class A and does it invoke move constructor of B?

  • Things get more worse for me: if I uncomment the lines of move operations in B, the initialization above will not compile complaining about referencing a deleted funtion, the same thing for the assignment!

Can anyone help me what happens exactly? I have googled and read in cppreference and many websites before posting the question here.

The output:

A'copy-ctor
A'copy-assign
A'copy-ctor
A'copy-assign

Done!

Aucun commentaire:

Enregistrer un commentaire