删除类复制构造函数时,无法使用使用等号表示法的类构造函数

时间:2019-05-31 21:50:25

标签: c++ constructor

在测试某些类时,我遇到了一个有趣的问题:如果使用等号(=)调用类构造函数(如果删除了复制构造函数),则会遇到错误错误:类型为“ Class”的复制变量会调用删除构造函数。使用括号时,代码可以正常编译。

这是怎么回事?这可以是编译器错误吗?

请考虑以下课程:

class Test
{
    public:
        int Int;

    public:
        Test() = default;
        Test(Test &) = delete;
        Test(Test &&) = delete;
        Test(int i)
        {
            Int = i;
        }
};

构造函数的调用方式如下:

Test t1(3);  //No error
Test t2 = 3; //error: copying variable of type 'Class' invokes deleted constructor

仅检查一下,我试图添加一些检查并允许这些功能和编译代码。 两个构造函数都以完全相同的方式使用MSVC 进行编译。

class Test
{
    public:
        int Int;

    public:
        Test()
        {
            Int = 0;
            cout << "Constructor";
        }
        Test(Test &t)
        {
            Int = t.Int;
            cout << "Copy Constructor";
        }
        Test(Test &&t)
        {
            Int = t.Int;
            cout << "Move Constructor";
        }
        Test(int i)
        {
            Int = i;
            cout << "Constructor from int";
        }
};
Test t1(3);  //Constructor from int
Test t2 = 3; //Constructor from int

这到底是怎么回事?

1 个答案:

答案 0 :(得分:1)

您正在看到copy elision规则的结果。

基本上,说T var = expr;expr构造一个未命名的临时文件,然后使用复制或移动构造器将其复制或移动到var中。如果复制和移动构造函数被删除,则将给出有关已删除构造函数的错误。但是,然后需要编译器直接从var中删除复制或移动并构造expr,即使复制或移动构造函数具有明显的副作用。它是由语言设计引起的那些奇怪的极端情况之一,这些语言是通过对不同实现的实际作用(或过去某个时候所做的事情)进行事实上的标准化,加上按委员会设计和随着时间的推移缓慢发展,同时试图保持向后兼容

see here进行更多讨论