显式删除的移动构造函数

6

为什么会这样:

struct A
{
    A(int) {
        cout << "construct from int" << endl;
    }

    A(A&&) = delete;

    A(const A &) {
        cout << "copy constructor" << endl;
    }
};

int main(){
    A a = 0;
}

出现错误:

error: use of deleted function ‘A::A(A&&)’

为什么当我添加这样的移动构造函数时

A(A&&) {
    cout << "move constructor" << endl;
}

程序编译正常,但输出为空。

construct from int

据我所知,编译器要求构造函数但不使用它。为什么?这对我来说毫无意义。
附注:我认为
A a = 0;

等同于

A a = A(0);

但为什么既没有调用移动构造函数,也没有调用移动赋值运算符呢?


你使用的编译器是哪个? - Brotcrunsher
2
这在C++17中已经改变了(删除的移动构造函数现在可以编译),但复制/移动省略在此之前一直存在。 - chris
我在g++4.9、g++6.3和clang 5.0上尝试了它,都是一样的。 (-O0 -std=c++11) - Islam Boziev
确实,在clang 5上使用-std=c++17可以编译通过。 - Islam Boziev
2
现在给你一些不请自来的建议:https://www.youtube.com/watch?v=vLinb2fgkHk&t=55m51s - Howard Hinnant
1个回答

4
根据C++标准(12.8复制和移动类对象)
在满足某些条件的情况下,即使所选的构造函数和/或对象的析构函数具有副作用,实现也可以省略类对象的复制/移动构造,对于这种情况,实现将省略的复制/移动操作的源和目标视为只是引用同一对象的两种不同方式,并且该对象的销毁发生在这两个对象将在没有优化的情况下被销毁的时间中较晚的一个。 这种复制/移动操作的省略,称为复制省略,可以在以下情况下进行(可以组合以消除多个副本):....当尚未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同cv非限定类型的类对象时,可以通过直接将临时对象构造到被省略复制/移动的目标中来省略复制/移动操作。
并且
如果对象的复制/移动构造函数或复制/移动赋值运算符被隐式odr使用并且无法访问特殊成员函数(第11条款),则程序无效。[注意:使用复制/移动构造函数或复制/移动赋值运算符将一个对象复制/移动到另一个对象中不会更改任何对象的布局或大小。-注]

我发现很难理解这个标准,你能给一些解释或示例代码吗? - Hải Phạm Lê
@HảiPhạmLê 只需要阅读加粗的文本即可。问题中还提供了示例代码。 - Vlad from Moscow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接