学习C++,很少有关于构造函数的问题。
请考虑以下代码:
#include<stdio.h>
#include<iostream>
// Case 1
class CFoo
{
public:
CFoo() { printf("CFoo constructor: user-defined default\n"); }
~CFoo() { printf("CFoo destructor\n"); }
};
void testFoo()
{
CFoo foo0; // A way to use default constructor
CFoo foo1 = CFoo(); // Another way to use default constructor
CFoo foo2 = CFoo(foo1); // Using implicit copy constructor
// Output:
// CFoo constructor: user-defined default
// CFoo constructor: user-defined default
// CFoo destructor
// CFoo destructor
// CFoo destructor
// CFoo destructor
}
// Case 2
class CBar
{
public:
CBar() { printf("CBar constructor: user-defined default\n"); }
CBar(CBar & other) = delete;
~CBar() { printf("CBar destructor\n"); }
};
void testBar()
{
CBar bar0;
// line 44: error C2280: 'CBar::CBar(CBar &)': attempting to reference a deleted function
// line 34: note: see declaration of 'CBar::CBar'
// line 34: note: 'CBar::CBar(CBar &)' : function was explicitly deleted
// CBar bar1 = CBar(); // Why this has anything to do with the copy constructor?
// Output:
// CBar constructor: user-defined default
// CBar destructor
}
// Case 3
class CBaz
{
public:
CBaz() { printf("CBaz constructor: user-defined default\n"); }
CBaz(CBaz & other) { printf("CBaz constructor: user-defined copy\n"); }
~CBaz() { printf("CBaz destructor\n"); }
};
void testBaz()
{
CBaz baz0;
CBaz baz1 = CBaz();
CBaz baz2 = CBaz(baz1);
// Output:
// CBaz constructor: user-defined default
// CBaz constructor: user-defined default
// CBaz constructor: user-defined copy
// CBaz destructor
// CBaz destructor
// CBaz destructor
}
// main
void main() {
testFoo();
testBar();
testBaz();
std::cin.get();
}问题:
CBar bar1 = CBar();一样创建一个CBar bar1 = CBar();实例testFoo调用4个析构函数。其中3种为foo0、foo1和foo2。第四个从何而来?testBaz具有相同的结构,但只调用3个析构函数。CFoo和CBaz之间唯一的区别是CBaz具有用户定义的复制构造函数。发布于 2017-09-15 17:10:20
CBar bar1 = CBar();一样创建一个CBar bar1 = CBar();实例删除CBar的复制构造函数。因此,CBar是不可复制的。因此,不能复制初始化CBar。
CFoo是可以复制的,所以没有问题。
CBar bar1 = CBar();//为什么这与复制构造函数有任何关系?
T object = other;是用于复制初始化的语法。
除了命名对象(变量),还有两个临时对象,CFoo()和CFoo(foo1)。无论出于什么原因,只有其中一位临时人员通过复制筛选而被优化。
testBaz具有相同的结构,但只调用3个析构函数。
这在某种程度上影响了操作系统。我看不出为什么两个CFoo`临时代码都不可能被优化掉,但是其中一个没有被优化,因为我的编译器确实对两者进行了优化。
PS。CBaz baz1 = CBaz();格式不正确,因为非const值引用不能绑定到临时引用。
PPS。void main()格式错误,因为main必须返回int。
发布于 2017-09-15 17:15:43
CBar bar1 = CBar();不是分配,而是使用复制/移动构造函数进行初始化。
即使被省略,移动/复制构造函数也应该是可访问的。
由于使用了保护省略的C++17,规则已经改变,而且CBar bar1 = CBar();不要求移动/复制构造函数是可访问的,它相当于CBar bar1{};。
发布于 2017-09-15 17:11:05
这是直接初始化:
CFoo foo0;这是副本初始化:
CBaz baz1 = CBaz();由于https://en.wikipedia.org/wiki/Copy_elision,复制初始化在性能上等同于直接初始化,而在语义上则不然;复制初始化仍然需要一个可访问的副本构造函数。
四个析构函数输出中有两个来自用CFoo的默认复制构造函数构造的实例。注意,打印的数量取决于优化:当复制省略优化打开时,对中间情况(即CFoo foo1 = CFoo() )的复制构造函数的调用可以优化出来,因此可以得到三个输出,而不是四个。CFoo foo2 = CFoo(foo0)右侧的副本没有优化。
https://stackoverflow.com/questions/46244513
复制相似问题