Reputation: 313
error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
Why is the copy constructor called only when there is a virtual destructor in A
? How to avoid this?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
Upvotes: 21
Views: 1369
Reputation: 180490
virtual ~A() = default;
is a user declared destructor. Because of that, A
no longer has a move constructor. That means return tmp;
can't move tmp
and since tmp
is not copyable, you get a compiler error.
There are two ways you can fix this. You can add a move constructor like
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
or you can create a base class that has the virtual destructor and inherit from that like
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
This works because A
no longer has a user declared destructor (Yes, C
does but we only care about A
) so it will still generate a move constructor in A
. The important part of this is that C
doesn't have a deleted move constructor, it just doesn't have one period, so trying to move it will cause a copy. That means
C
's copy constructor is called in A
's implicitly generated move constructor since C(std::move(A_obj_to_move_from))
will copy as long as it doesn't have a deleted move constructor.
Upvotes: 33