当用“class_name obj_name {func()}”替换“class_name obj_name = func()”时有意义吗?

时间:2013-04-02 08:37:32

标签: c++ assign initializer-list

在代码中,我看到以下构造:

const class_name obj_name{func()};

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

const class_name obj_name = func();

2 个答案:

答案 0 :(得分:5)

const class_name obj_name{func()};

通过编写上述内容,作者试图遵循统一初始化语法(由C ++ 11引入),以避免由 vexing parse 引起的问题。 最令人烦恼的解析,甚至有经验的程序员也会陷入困境。他试图将最佳实践灌输到他的大脑中,这样他就不会偶尔陷入上述解析问题,如下所述。

考虑一下,

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!

那是制服,当然最好的做法,不是吗?

希望有所帮助。

答案 1 :(得分:1)

从C ++ 11开始,引入了uniform initialization功能,它提供了几种初始化类型的方法。

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

需要注意的是{}语法在这种情况下的行为并不总是如此:如果有一个相应类型的initialization_list构造函数,则使用该构造函数,否则使用适当的构造函数初始化类元素。

如果 Most Vexing Parse 原则(如果它可能被解释为函数原型,那么它将会发生)罢工你需要使用其中任何一个告诉编译器以下不是函数原型:

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