我正在研究C++,并创建了这个简单的代码来练习复制构造函数。
class Cube{
private:
double length;
public:
Cube(){
length = 1;
cout << "default constructor called" << endl;
};
Cube(const Cube& obj){
length = obj.length;
cout << "copy constructor called" << endl;
};
};
Cube foo(){
Cube c;
return c;
}
int main(){
Cube c2 = foo();
return 0;
}我希望这能打印出来
“默认构造函数名为”
“复制构造函数已调用”
“复制构造函数已调用”
因为在“立方体C”中调用默认构造函数,而在“返回c”和“立方体c2 = foo()”中调用复制构造函数。
然而,我的控制台只显示“默认构造函数名为”
我是不是误解了拷贝构造函数的工作方式?
发布于 2020-06-02 14:36:01
这不会调用您的复制构造函数,而是foo中创建的对象被初始化为c2。
Cube c2 = foo();这将调用=赋值运算符:
Cube c2; // default constructor
c2 = foo(); // default constructor inside foo() and then assignment operator这将调用复制构造函数:
Cube c3; // default constructor
Cube c2(c3); // copy constructor复制构造函数的语法为:
Cube(const Cube& obj)它是一个从另一个对象创建一个对象副本的构造函数。
发布于 2020-06-02 15:25:46
但是我的控制台只显示"default constructor called“
因为copy elision。
你的期望是对的。在概念上有两个拷贝结构,第一个是return c;,copy-initialize来自c的返回值;第二个是Cube c2 = foo();,copy-initialize c2来自foo()的返回值。由于copy elision的原因,它们都被省略了,那么复制构造函数根本就不会被调用。
对于第一个,
当操作数是具有自动存储持续时间的非易失性对象的名称,不是函数参数或catch子句参数,并且与函数返回类型相同的类类型(忽略cv-
)时,返回语句中的限定。这种副本省略的变体被称为NRVO,即“命名返回值优化”。
对于第二个,
当初始化器表达式是与变量类型相同类类型(忽略cv-
)的pr值时,对象初始化中的限定:
T x=T(T(f();//只调用一次T的默认构造函数,初始化x
请注意,第二个是强制的,因为C++17。
顺便说一句:在C++17之前的模式下编译(避免强制的复制遗漏)和-fno-elide-constructors选项(避免潜在的复制遗漏)会得到您所期望的结果。LIVE with gcc
https://stackoverflow.com/questions/62146129
复制相似问题