C++ 两个初始化之间的区别是什么:Foo f();Foo f=Foo()

C++ 两个初始化之间的区别是什么:Foo f();Foo f=Foo(),c++,C++,我发现当我向private声明Foo(constfoo&)时,foof1=Foo()不编译。所以我认为Foo f1=Foo();只需调用复制构造函数,但当我将代码更改为: class Foo { public: Foo(){} private: Foo(const Foo &); }; Foo f(); Foo f1 = Foo(); class-Foo { 公众: Foo(){} Foo(const Foo&){std::cout,因为不必调用复制构造函数。但复制构

我发现当我向private声明
Foo(constfoo&)
时,
foof1=Foo()不编译。所以我认为
Foo f1=Foo()
;只需调用复制构造函数,但当我将代码更改为:

class Foo
{
public:
    Foo(){}
private:
    Foo(const Foo &);
};

Foo f();
Foo f1 = Foo();
class-Foo
{
公众:
Foo(){}
Foo(const Foo&){std::cout,因为不必调用复制构造函数。但复制构造函数必须仍然作为公共成员存在

Foo f();
声明一个名为
f
的函数,不带任何参数,并按值返回
Foo
对象。

由于不必调用复制构造函数,因此复制构造函数必须仍然作为公共成员存在


Foo f();
声明一个名为
f
的函数,不带任何参数,并按值返回
Foo
对象。

为了回答实际问题,正式地说,代码

class Foo
{
public:
    Foo(){}
    Foo(const Foo &){std::cout<<"Foo(const Foo &)";}

};

Foo f();
Foo f1 = Foo();
使用默认构造函数创建类型为
Foo
的临时对象,并使用复制构造函数将
f1
构造为该临时对象的副本,然后销毁该临时对象

Foo f1 = Foo();
使用默认构造函数创建
f

与复制构造函数的这种小小的舞蹈并不像听起来那么低效。在过去,只要可以访问复制构造函数,编译器就可以跳过临时的,直接初始化
f1
。这被称为“复制省略”。生成的代码与
Foo f1;
相同。但是,如果
Foo
没有副本构造函数,或者在初始化时无法访问该构造函数(例如,副本构造函数是私有的,初始化未在成员函数内完成),则该代码无效

然后,复制省略变成了强制性的:编译器不再只允许跳过临时的;它是必需的


现在,显然,甚至不再要求复制构造函数存在并且可以访问;编译器需要将第一种形式转换为第二种形式,因此这两种形式是相同的,以回答实际问题,正式地说,代码

class Foo
{
public:
    Foo(){}
    Foo(const Foo &){std::cout<<"Foo(const Foo &)";}

};

Foo f();
Foo f1 = Foo();
使用默认构造函数创建类型为
Foo
的临时对象,并使用复制构造函数将
f1
构造为该临时对象的副本,然后销毁该临时对象

Foo f1 = Foo();
使用默认构造函数创建
f

与复制构造函数的这种小小的舞蹈并不像听起来那么低效。在过去,只要可以访问复制构造函数,编译器就可以跳过临时的,直接初始化
f1
。这被称为“复制省略”。生成的代码与
Foo f1;
相同。但是,如果
Foo
没有副本构造函数,或者在初始化时无法访问该构造函数(例如,副本构造函数是私有的,初始化未在成员函数内完成),则该代码无效

然后,复制省略变成了强制性的:编译器不再只允许跳过临时的;它是必需的


现在,显然,甚至不再要求复制构造函数存在并且可以访问;编译器需要将第一种形式转换为第二种形式,因此在C++17中,这两种形式是相同的,因此不再需要复制构造函数。在C++17之前,复制构造函数在C++17中不能是显式的++17复制构造函数不再是必需的。在C++17之前,复制构造函数不能是显式的。区别在于第一个不是初始化。它是一个函数声明,就像
int f()但这不是真正的问题。区别在于第一个不是初始化。它是一个函数声明,就像
int f();
。但这不是真正的问题。