关于复制构造函数的一个棘手问题

A tricky question regarding Copy Constructor

我的困惑在于第 Cube c = a; 行。我认为它应该同时调用默认构造函数和复制构造函数,但实际上它只调用复制构造函数。 难道 Cube cCube a 一样,不是一个应该调用默认构造函数的新对象吗?

class Cube 
{ 
    public:
        int length_;

        Cube(){
            length_ = 1; 
            cout<< "Default Constr"<< endl; 
        }

        Cube(const Cube & obj){
            length_ = obj.length_;
            cout<< "Copy Constr"<< endl;
        }

}; 

Cube foo(){
    Cube c;
    return c; 
}

int main() { 
    Cube a; //invoke default constructor only
    Cube c = a; //invoke copy constructor only


    return 0; 
} 

调用默认构造函数。 它用于初始化对象。 然后复制构造函数用于将新对象的状态设置为与初始对象相同。

当你写:

Cube c = a;

这实际上不是作业,而是 copy-initialization

在你的情况下,这与你写的一样:

Cube c(a);

只调用复制构造函数。

请记住,一个对象只构造一次,因此只有一个构造函数。

正如其他人所指出的,您这里的是复制初始化,因此无法使用默认构造函数。

有一种稍微不同的情况,其中复制初始化可以(至少理论上)涉及一个额外的步骤。考虑这样的代码:

class foo { 
public:
    foo(int) {}
};

int main() { 
    foo f = 1;
}

在这种情况下,(至少在 C++17 之前)理论上应该涉及两个独立的构造函数。首先,构造一个临时对象,用 1 初始化,然后调用复制构造函数从该临时对象初始化 f

在这种情况下,大多数编译器将生成直接从 q 初始化 f 的代码,因此它等同于 foo f{1};。编译器仍然需要尊重需要副本的事实,因此如果删除复制构造函数,编译将失败:

class foo { 
    foo(foo const &)= delete;
public:
    foo(int) {}
};

int main() { 
    foo f = 1;
}

结果(使用 gcc):

trash9.cpp: In function 'int main()':
trash9.cpp:8:17: error: use of deleted function 'foo::foo(const foo&)'
         foo f = 1;
                 ^
trash9.cpp:2:9: note: declared here
         foo(foo const &) = delete;
         ^~~
trash9.cpp:4:9: note:   after user-defined conversion: 'foo::foo(int)'
         foo(int) {}
         ^~~

但是从 C++17 开始的规则的变化意味着现在即使这样也是允许的(所以如果我在上面的编译中添加 -std=c++17,它就会成功)。