为啥这段代码试图调用复制构造函数?

Posted

技术标签:

【中文标题】为啥这段代码试图调用复制构造函数?【英文标题】:Why is this code trying to call the copy constructor?为什么这段代码试图调用复制构造函数? 【发布时间】:2012-02-17 23:56:05 【问题描述】:

我只是在 Visual Studio 中花费了大量时间来处理编译错误。我已将代码提炼成下面的可编译的小示例,并在 IdeOne 上进行了尝试,得到了相同的错误,您可以看到 here。

我想知道为什么下面的代码会尝试调用B(const B&) 而不是B(B&&)

#include <iostream>

using namespace std;

class A 
public:
    A() : data(53)  
    A(A&& dying) : data(dying.data)  dying.data = 0; 

    int data;

private:
    // not implemented, this is a noncopyable class
    A(const A&);
    A& operator=(const A&);
;

class B : public A  ;

int main() 
    B binst;

    char* buf = new char[sizeof(B)];

    B* bptr = new (buf) B(std::move(binst));

    cout << bptr->data << endl;

    delete[] buf;

我没有明确定义任何构造函数,所以B(std::move(binst)) 应该调用编译器生成的B(B&amp;&amp;),不是吗?

当我将B 更改为

class B : public A 
public:
    B()  
    B(B&&)  
;

它编译得很好。这是为什么呢?

如果不能从基类修复这将非常不方便,因为我有一个模板类,它使用像示例这样的放置 new 和移动构造函数,并且它需要每个不可复制的类(这不是并且绝对不应该是与我的模板类一起使用的要求)具有明确定义的移动构造函数。

【问题讨论】:

是否有编译器生成B(B&&)?我的 C++11 还是有点生疏。你的 B(B&&) 需要初始化 A(A&&) 吗? @CashCow 是的,它所做的只是移动每个成员(如果那是错误的,那么我正在看着你,Kerrek SB :) 在 GCC 4.6、GCC 4.7 和 Clang 3.0 上编译良好。 @CashCow:应该有,但是VS2010没有。 在 GCC 4.6.2 上运行良好。 【参考方案1】:

如果您使用的是 Visual Studio 2010 或 2012,请注意:编译器不会自动为您生成移动构造函数。那没有实施。所以你需要自己写。

【讨论】:

应该注意的是,何时应该将移动构造函数隐式定义为默认值的细节在标准化过程即将结束时发生了变化,而 vc2010 在此之前就已经存在。另外,vc2010 不支持= delete,这使得我们很难谈论移动构造函数的一致性:) 这很烦人。我渴望VS11。谢谢。 @Seth Carnegie: VC11 也不会自动生成移动构造函数...blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx "右值引用 v3.0 增加了新规则以在某些条件下自动生成移动构造函数和移动赋值运算符。这将在 VC11 中没有实现,它将继续遵循 VC10 永远不会自动生成移动构造函数/移动赋值运算符的行为。”【参考方案2】:

您必须面临编译器错误。标准说B 得到一个隐式声明和定义的移动构造函数;满足 12.8(9) 的所有条件(即 B 没有显式声明的复制构造函数、复制赋值等,并且移动构造函数不会隐式声明为 deleted)。

【讨论】:

我想这就是我使用 VS 得到的结果,VS 是一个在标准之间编写的编译器。谢谢。

以上是关于为啥这段代码试图调用复制构造函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥从类构造函数调用的方法应该是最终的? [复制]

为啥隐式复制构造函数调用基类复制构造函数而定义的复制构造函数不调用?

当我们将对象作为参数传递给方法时,为啥会调用复制构造函数?

为啥不在构造函数中调用可覆盖的方法?

将右值按值传递给函数时,为啥不调用复制构造函数

为啥在malloc中不调用构造函数? [复制]