3

在重复的呼喊开始之前:我知道以下问题(和其他一些问题)与这个问题非常相关:

复制初始化和直接初始化在 C++ 中有区别吗?

这个问题的答案完美地解释了无法进行复制初始化的场景,并解释了两者的区别以及所有这些东西。但是,我的问题更微妙:

考虑代码:

A createA(){...}

A a1 = createA();
A a2(createA());

假设 A 可以隐式复制构造和所有这些东西,所以 和 的初始化a1a2很好。的复制构造函数中没有副作用A,因此两个初始化在语义上也是等效的。createA()直接返回变量的类型,而不是必须首先转换的其他内容。我认为这种情况很常见。

那么,在这种情况下,如果两种替代方案同样适用且在语义上等价,我应该使用哪一种?规范中是否有建议或社区中的共识/最佳实践,还是由我和我的编码风格决定使用哪一种?与旧标准相比,C++11 有什么不同吗?

4

2 回答 2

2

如果其他一切都相同(语义、性能……),那显然只是品味和/或风格惯例的问题。然而,现在许多作者提倡使用列表初始化器进行直接初始化:

A a3 {createA()};

但我想说,这取决于您(如果这是您的有趣项目)或您的同事来决定两(三)个替代方案之一。我建议将两者互换使用,因为这会让读者想知道为什么您有时使用直接初始化,有时使用复制初始化。

于 2013-02-25T12:48:14.913 回答
1

没有“总是更好”的答案,这是风格问题。

从对象类型的简单表达式(例如createA())初始化对象时,我经常使用 copy-init,可能只是因为熟悉=赋值形式。否则,当初始化器是不同类型或对象有多个初始化器(例如,多个构造函数参数或聚合初始化)时,我更喜欢使用 C++11 列表初始化(又名统一初始化语法),它可以用于更多的地方,例如初始化聚合以及具有用户定义构造函数的类,并且不能被解析为函数声明:

A a1{ createA() };

上面的 list-init 形式使用 direct-init,而这种形式使用 copy-init:

A a2 = { createA() };

使用 list-init 时,我更喜欢没有多余=符号的直接​​初始化形式。

There are a few cases where list-init isn't possible, e.g. when a type has an initializer-list constructor (i.e. one taking a parameter that is a specialization of std::initializer_list) and you want to call a different constructor, but the initializer-list constructor would get chosen, e.g. std::vector<int> v{ 5u, 0 }; will not create a vector of five elements with value zero, but a vector with two elements with values five and zero

于 2013-02-25T12:49:11.020 回答