【问题标题】:c++ move constructor generated with default constructorc++ 使用默认构造函数生成移动构造函数
【发布时间】:2016-12-16 08:09:00
【问题描述】:

查看this question,它只提到C++11 及更高版本

如果没有用户声明的复制构造函数、复制赋值运算符或析构函数,并且生成的移动构造函数是有效的(例如,如果它不需要分配常量成员),则移动构造函数是自动生成的(§12.8 /10)。

所以如果我有以下代码:

class Y
{
public:
    Y(const Y&) {}
};

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem; 
};
hasY hy, hy2 = std::move(hy); //this line fails as expected as Y has a user-defined copy constructor.

现在如果我将默认构造函数添加到 Y:

Y() {}

错误消失了。
它在哪里说默认构造函数导致创建移动构造函数?

(使用 VS 2015 更新 2)

【问题讨论】:

  • 默认构造函数不会导致创建移动构造函数。代码中的错误是由于hasY hy 无法完成,因为mem 没有可访问的构造函数。您可以通过提供这样的构造函数来解决此问题。编译器错误消息应表明这一点。如果您发布确切的编译器输出可能会有所帮助。
  • @M.M 如果我有:hasY hy;并且 Y 没有默认构造函数,错误是:hasY::hasY(void)':尝试根据您所说的引用已删除的函数。但这仍然不能解释为什么它使用 hy2 = std::move(hy); 成功构建;现在。
  • 是的,“删除的函数”是hasY的构造函数,因为mem没有可访问的构造函数而被删除

标签: c++ c++11 constructor


【解决方案1】:
class Y
{
public:
    Y(const Y&) {}
};

这个类没有默认构造函数,所以

struct hasY {
    hasY() = default;
    hasY(hasY&&) = default;
    Y mem;  // << requires default ctor
};

您遇到的错误与移动构造函数无关:

prog.cpp: In function 'int main()':
prog.cpp:13:7: error: use of deleted function 'hasY::hasY()'
  hasY hy;
   ^
prog.cpp:8:5: note: 'hasY::hasY()' is implicitly deleted because the default definition would be ill-formed:
     hasY() = default;

http://ideone.com/u46GWS

【讨论】:

    【解决方案2】:

    与移动构造函数无关它与默认构造函数有关。试试这个:

    class Y
    {
    public:
        Y(const Y&) {}
    };
    
    struct hasY {
        hasY() = default;
        hasY(hasY&&) = default;
        Y mem; 
    };
    hasY hy; // This will cause an error because there is no default constructor
    

    现在如果你添加默认构造函数:Y(){},错误就会消失。


    正如@M.M 所说,在这种情况下将调用复制构造函数。

    你可以试试这个代码:

    class Y{
    public:
        Y(){std::cout << "Default constructor\n";}
        Y(const Y&) {std::cout << "Copy constructor\n";}
    };
    
    struct hasY {
        hasY() = default;
        hasY(hasY&&) = default;
        Y mem; 
    };
    
    int main(){
        hasY hy;
        hasY h=std::move(hy);
    }
    

    它将打印:

    默认构造函数

    复制构造函数

    如果你想让类不可移动,你应该自己删除移动构造函数Y(Y&amp;&amp;)=delete;

    【讨论】:

    • 好的,那么有了用户定义的默认构造函数和复制构造函数,移动构造函数不会被自动删除吗?即不应该 hy2 = std::move(hy) 无法编译?
    • @tomatoRadar 在这种情况下将不存在移动构造函数(“不存在”与“已删除存在”不同),因此hy2 = std::move(hy) 将使用复制构造函数
    • @M.M - 我明白了....这是 C++11 的行为。因此隐式声明的移动构造函数将被删除,但不参与 C++14 的重载决议。
    • @tomatoRadar 在这种情况下没有隐式声明的移动构造函数。
    【解决方案3】:

    哪里说默认构造函数导致创建移动构造函数?

    移动构造函数的创建与默认构造函数的存在或缺失之间没有关系。

    来自 C++11 标准:

    12.8 复制和移动类对象

    ...

    9 如果类 X 的定义没有显式声明移动构造函数,则会隐式声明 默认当且仅当

    — X 没有用户声明的复制构造函数,

    ——X 没有用户声明的复制赋值运算符,

    — X 没有用户声明的移动赋值运算符,

    ——X 没有用户声明的析构函数,并且

    ——移动构造函数不会被隐式定义为已删除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-17
      • 2013-01-23
      • 2020-05-14
      • 2014-05-15
      • 1970-01-01
      相关资源
      最近更新 更多