如何解决从具有用户声明的 dtor 和移动支持的抽象基础派生
用户声明的 dtor 阻止自动生成 move-ctor/-assignment-operator, 但是只有在定义了 dtor 的类中才会阻止自动生成,还是在所有派生类中也会阻止自动生成?我问这个,因为我使用了许多纯虚拟类,它们都提供用户声明的 dtor。我现在必须升级所有这些类才能获得移动支持还是开箱即用?
以下是我的场景当前的示例:
struct BigData {};
struct BaseA
{
virtual void func() = 0;
virtual ~BaseA() = default;
};
struct A : public BaseA
{
BigData _data;
void func() override {}
};
现在,我必须使用以下哪些变体 可以肯定,移动将在下面使用 例子?
A a;
std::vector< A > va;
va.push_back( std::move( a ) ); //Should really use move instead of copy
变体 1:仅升级基类
struct BaseA
{
virtual void func() = 0;
virtual ~BaseA() = default;
BaseA() = default;
BaseA(BaseA&&) = default;
BaseA& operator=(BaseA&&) = default;
BaseA(const BaseA&) = default;
BaseA& operator=(const BaseA&) = default;
};
struct A : public BaseA
{
BigData _data;
void func() override {}
};
变体 2:仅升级派生类
struct BaseA
{
virtual void func() = 0;
virtual ~BaseA() = default;
};
struct A : public BaseA
{
BigData _data;
void func() override {}
A() = default;
A(A&&) = default;
A& operator=(A&&) = default;
A(const A&) = default;
A& operator=(const A&) = default;
};
变体 3:升级基类和派生类
struct BaseA
{
virtual void func() = 0;
virtual ~BaseA() = default;
BaseA() = default;
BaseA(BaseA&&) = default;
BaseA& operator=(BaseA&&) = default;
BaseA(const BaseA&) = default;
BaseA& operator=(const BaseA&) = default;
};
struct A : public BaseA
{
BigData _data;
void func() override {}
A() = default;
A(A&&) = default;
A& operator=(A&&) = default;
A(const A&) = default;
A& operator=(const A&) = default;
};
变体 4:无事可做
解决方法
在基类中没有移动构造函数与在基类中具有已删除的移动构造函数是两件不同的事情。
对于第一个,派生类仍然可以遵循零规则,并具有编译器创建的默认生成移动构造函数。
对于后者,在派生中也会删除默认的移动。
当您的类中有用户定义的析构函数(或用户定义的复制构造函数,或用户定义的复制赋值运算符)时,不会提供默认的移动操作,但不会隐式删除它们。因此,如果派生类遵循默认移动操作的规则,则它仍然有权进行默认移动操作,而无需将它们显式声明为 =default
。
Cpp 参考 says:
如果满足以下任一条件,则类 T
的隐式声明或默认移动构造函数被定义为已删除:
...
T
具有无法移动的直接或虚拟基类(已删除、不可访问或不明确的移动构造函数);
...
请注意,用户声明析构函数不会使类不可移动,它只是没有默认生成的移动。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。