class Foo
{
public:
Foo(){}
private:
Foo(const Foo &);
};
Foo f();
Foo f1 = Foo();
我发现当我将Foo(const Foo &)
声明为私有时,Foo f1 = Foo();
无法编译。因此我认为Foo f1 = Foo()
;只需调用复制构造函数,但是当我将代码更改为:
class Foo
{
public:
Foo(){}
Foo(const Foo &){std::cout<<"Foo(const Foo &)";}
};
Foo f();
Foo f1 = Foo();
它什么都不会打印。所以两次初始化Foo f(); Foo f = Foo()
有什么区别?
答案 0 :(得分:5)
由于copy elision,不必调用复制构造函数。复制构造函数仍然必须作为公共成员存在。
然后Foo f();
声明一个名为f
的函数,不接受任何参数,并按值返回一个Foo
对象。
答案 1 :(得分:1)
要正式回答实际问题,代码
Foo f1 = Foo();
使用默认构造函数创建类型为Foo
的临时对象,并使用复制构造函数将f1
构造为该临时对象的副本,然后销毁该临时对象。
Foo f;
使用默认构造函数创建f
。
使用复制构造函数进行的小动作并不是听起来那么低效。早在过去,只要可以访问复制构造函数,就可以允许编译器跳过临时副本,并直接初始化f1
。这称为“复制删除”。结果代码与Foo f1;
相同。但是,如果Foo
没有复制构造函数,或者在初始化时无法访问该构造函数(例如,复制构造函数是私有的,并且初始化未在成员函数内部完成),则代码无效。
然后必须取消复制:编译器不再只是允许跳过临时程序; 必需。
现在,显然,甚至不再需要复制构造函数存在并且可以访问;编译器需要将第一种形式转换为第二种形式,因此两者相同。