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 copy 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!