首页 > 解决方案 > 删除类复制构造函数时无法使用等号表示法使用类构造函数

问题描述

在测试一些类时,我遇到了一个有趣的问题:当使用等号表示法 (=) 调用类构造函数时,如果删除了复制构造函数,则会遇到错误 error: copying variable of type 'Class' invokes deleted constructor。使用括号时,代码可以正常编译。

这里发生了什么?这可能是编译器错误吗?

考虑以下类:

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

这里到底发生了什么?

标签: c++constructor

解决方案


您将看到复制省略规则的结果。

基本上,sayingT var = expr;构造一个未命名的 temp expr,然后var使用复制或移动构造器将其复制或移动到其中。如果复制和移动构造函数被删除,那么这将给出有关已删除构造函数的错误。但是,编译器需要var直接从中删除该复制或移动和构造expr,即使复制或移动构造函数具有可见的副作用。它是语言设计中出现的那些奇怪的极端案例之一,通过事实上标准化不同的实现所做的(或过去某个时间所做的),加上委员会设计和随着时间的推移缓慢演变,同时试图保持向后兼容性.

更多讨论见这里


推荐阅读