c++隐式复制和移动构造函数背后的基本原理
rationale behind c++ implicit copy and move constructor?
我对c++隐式复制构造函数的理解类似于
T(T const& x) :
base1(x), base2(x) ... ,
var1(x.var1), var2(x.var2)...
{}
移动构造函数,复制&移动分配也遵循类似的模式。
为什么它的定义不类似于以下内容
T(T const& x) :
base1(static_cast<base1 const&>(x)),
base2(static_cast<base2 const&>(x)) ... ,
var1(x.var1), var2(x.var2)...
{}
示例
我有一个类,它有隐式的复制/移动构造函数/赋值运算符,以及一些转换构造函数。我把工作委托给了某个实现类。
class common_work //common implementation of many work like classes
{
common_work(common_work const&) = default;
common_work(common_work&&) = default;// ... implicit constructors work for me.
//a forwarding constructor which can take many work like objects
template<class T, enable_if<work_like<T> > >
common_work(T&& x) { ... }
};
class work1 //one of the implementation
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
common_work impl_;
};
这很好,因为work1
的复制/移动构造函数正在为common_work
调用复制/移动构造器,而转发构造函数被从另一种work
转换而来的其他构造函数使用[代码中未显示]。
然后出于EBO等原因,我想从common_work
继承work1
。所以新的work1
类看起来像
class work1 : private common_work
{
work1(work1 const& ) = default;
work1(work1&& ) = default; ...
};
但是,由于work1
是work_like
类,转发构造函数突然变得更好匹配,因为common_work
的复制/移动构造函数需要从派生到基的static_cast
。
注意:
- Scott Meyers给出了一个类似的例子,其中复制构造触发转发构造函数,因为复制构造函数需要常量添加,而转发构造函数不需要。但我认为,这个问题是由于错误的类设计引起的,而这里的问题是由于隐式复制/移动过程中传递给基类的参数不完全匹配引起的
- 我不能写一个通用的转发构造函数/赋值,也不能删除隐式的,因为被删除的函数也会参与重载解决,如果完全匹配会导致错误
- 目前我的解决方案是将
common_work
作为CRTP,即作为模板参数传递的派生类类型,并在转发构造函数中将其过滤为enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >
。否则,我必须手动将work1
和static_cast
的复制/移动构造函数/赋值显式地写入基类,这是有缺陷的、容易出错的,并且有维护风险
这个问题几年前就在MSVC++错误生成器页面上讨论过(因此,如果它还没有修复,那么它就是MSVC++上的已知问题)。标准称
- 。。。基或成员直接用x的相应基或成员初始化
当我读到错误报告时,我确实测试了各种编译器,所有这些编译器都"神奇地抛出"了。标准似乎对细节保持沉默(也关于值类别和c/v限定符),只是说"有相应的基数……x",如果你把IMO的意思理解为"不是x,而是x的对应基…",而不是你把完整的对象传给它(我甚至会说它只能这样有意义),那么IMO就更有意义了。
相关文章:
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 使用dynamic_cast和构造函数时出错
- 在c++中使用向量时,如何调用构造函数和析构函数
- c++隐式复制和移动构造函数背后的基本原理