5

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

const class_name obj_name{func()};

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

const class_name obj_name = func();
4

2 回答 2

5
const class_name obj_name{func()};

写到上面,作者试图遵循统一的初始化语法(由 C++11 引入),以避免因vexing parsemost 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++中称为vexing parse 。

同样,一个人可以写这个(意外地),

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!

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

希望有帮助。

于 2013-04-02T08:42:13.643 回答
1

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

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

请注意,{}在这种情况下,语法并不总是如此:如果存在适当类型的 initialization_list 构造函数,则使用该构造函数,否则使用适当的构造函数初始化类元素。

如果最令人头疼的 Parse原则(如果它可能被解释为函数原型,那么它将是)发生,你需要使用两者中的任何一个来告诉编译器以下不是函数原型:

typename class_name obj_name(func());
class_name obj_name { func() };
于 2013-04-02T08:39:43.230 回答