c++ - C++ 隐式复制和移动构造函数背后的基本原理?

标签 c++ c++11 constructor assignment-operator perfect-forwarding

我对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)...
{}

示例

我有一个具有隐式复制/移动构造函数/赋值运算符的类,以及一些转换构造函数。我正在将这项工作委托(delegate)给某个实现类。

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 转换而来.

然后我想继承work1来自 common_work出于 EBO 和其他原因。所以新的work1类看起来像

class work1 : private common_work
{
   work1(work1 const& ) = default;
   work1(work1&& ) = default; ...
};

但是,work1work_like类,突然转发构造函数得到了更好的匹配,作为 common_work 的复制/移动构造函数需要 static_cast从派生到基础。

注意:

  • Scott Meyers 给出了一个类似的例子,其中复制构造触发转发构造函数,因为复制构造函数需要添加 const,而转发构造函数不需要。但我认为,这个问题是由于错误的类设计引起的,而这里的问题是由于在隐式复制/移动期间传递给基类的参数不完全匹配。
  • 我不能写一个通用的转发构造函数/赋值,并删除隐式的,因为删除的函数也参与重载决议,如果完全匹配会导致错误。
  • 我目前的解决方案是制作 common_work作为 CRTP ,即作为模板参数传递的派生类类型,并在转发构造函数中将其过滤为 enable_if<and_<work_like<T>,not_<is_same<T,Derived> > > > .否则我必须手动为 work1 编写复制/移动构造函数/赋值。和 static_cast明确地基类,这是错误的、容易出错和维护的危险。

最佳答案

几年前在 MSVC++ bugtracker 页面上讨论了此问题(因此,如果尚未修复,则它是 MSVC++ 上的一个已知问题)。标准说

  • ... the base or member is direct-initialized with the corresponding base or member of x.

当我阅读错误报告时,我确实测试了各种编译器,所有这些编译器都“神奇地转换”了。该标准似乎在细节上保持沉默(也关于值类别和 c/v 限定符),只是说“具有 x 的相应基数”,如果您认为这意味着 IMO 更有意义“不是 x,而是 x 的相应基 ...”,而不是您将完整的对象传递给它(我什至会说它可以 only 以这种方式有意义) .

关于c++ - C++ 隐式复制和移动构造函数背后的基本原理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17716461/

相关文章:

c++ - 将模板类作为参数传递

java - 为什么我得到空对象数组的 NullPointerException 但该对象具有默认构造函数?

c++ - "onEachSubelement(...)"C++ 方法

c++ - 标准 12.1 p14 中的 "unspecified value"是什么意思?

C++继承方法调用基类的方法而不是重载方法

c++ - 使用 Windows 消息检测媒体插入驱动器

c++ - 计算机如何计算平方根?

c++ - 在 C 程序中使用 C++ 库

c++ - 仅从另一个类创建类/句柄

c++ - 不同翻译单元中具有静态存储持续时间的依赖非局部常量浮点变量的常量初始化