什么时候用"class_name obj_name{func()}"替换"class_name obj_name = func()"有意义?

When it make sense to replace "class_name obj_name = func()" by "class_name obj_name{func()}"?

本文关键字:name class func obj 有意义 替换 什么时候      更新时间:2023-10-16

在代码中我看到以下结构:

const class_name obj_name{func()};

func()返回一个名为class_name的类对象。所以,我想知道为什么不使用以下结构:

const class_name obj_name = func();
const class_name obj_name{func()};

通过编写以上内容,作者试图遵循统一的初始化语法 (c++ 11引入),以避免令人烦恼的解析最令人烦恼的解析所引起的问题,即使是经验丰富的程序员也会偶然陷入其中。他试图将最佳实践灌输到他的大脑中,这样他就不会像下面解释的那样偶尔陷入上述解析问题的困境。

考虑这个,

struct X { /*....*/ }; // some class
struct Y 
{
    Y();
    Y(int i);
    Y(X x);
};

现在可以这样写:

Y y(100); // declare an object y of type Y

调用第二个构造函数,这是可以的。到目前为止,一切都很好!

但意外的是有人甚至这样写:

Y y(); 

(错误地)认为它调用了默认构造函数。但事实是,它不调用默认构造函数。相反,它声明了一个不带参数的函数y,并返回Y。这在c++中叫做解析

同样地,也可以(偶然地)这样写:

Y y(X());

认为它调用了传递动态创建的X类型对象的第三个构造函数。这又是错误的。相反,它声明了一个函数y,它接受一个函数指针(函数类型不接受任何参数并返回X)并返回Y。它被称为, c++中最令人烦恼的解析

所以统一的初始化语法避免了所有这些问题,你可以这样写:
Y y1{};      // invokes 1st constructor
Y y2{100};   // invokes 2nd constructor
Y y3{X{}};   // invokes 3rd constructor

和遵循相同语法的

Y { function_call() }; 
const class_name obj_name { func() }; // taken from your question!

这是统一的,当然是最佳实践,不是吗?

希望对你有帮助。

从c++ 11开始,引入了统一初始化特性,提供了几种初始化类型的方法。

在这种情况下,两种语法都将调用class_name(class_name const&)复制构造函数(如果存在的话)。因此没有真正的区别。这只是个人喜好的问题。

需要注意的是,{}语法在这种情况下并不总是表现得像这样:如果有适当类型的initialization_list构造函数,则使用该构造函数,否则使用适当的构造函数初始化类元素。

最令人烦恼的解析原则(如果它可能被解释为函数原型,那么它将是)的情况下,您需要使用两者中的任何一个来告诉编译器以下不是函数原型:

typename class_name obj_name(func());
class_name obj_name { func() };