error: use of deleted function 'A::A(const A&)'
return tmp;
^~~
为什么仅在A
中存在虚拟析构函数时才调用复制构造函数?如何避免这种情况?
struct B {};
struct A{
std::unique_ptr<B> x;
virtual ~A() = default;
};
A f() {
A tmp;
return tmp;
}
答案 0 :(得分:30)
virtual ~A() = default;
是用户声明的析构函数。因此,A
不再具有move构造函数。这意味着return tmp;
无法移动tmp
,并且由于tmp
是不可复制的,因此会出现编译器错误。
有两种方法可以解决此问题。您可以添加一个移动构造函数,如
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;
};
或者您可以创建具有虚拟析构函数的基类,并像这样从其继承
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
之所以可行,是因为A
不再有用户声明的析构函数(是的,C
确实有,但我们只关心A
),因此它仍会在{{1 }}。重要的部分是A
没有删除的move构造函数,它没有一个句点,因此尝试移动它会导致复制。那意味着
C
的副本构造函数在C
的隐式生成的move构造函数中被调用,因为A
只要没有删除的move构造函数就会进行复制。