假设我有这样一个函数:
void my_test()
{
A a1 = A_factory_func();
A a2(A_factory_func());
double b1 = 0.5;
double b2(0.5);
A c1;
A c2 = A();
A c3(A());
}
在每一组中,这些陈述是否相同?或者在某些初始化中是否存在额外的(可能是可优化的)副本?
我见过有人两种说法都说。请引用原文作为证明。也请添加其他案例。
就这部分回答:
A c2 = A();c3 (());
由于大多数答案都是c++11之前的,我补充了c++11必须说的:
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6)
followed by a parenthesized expression-list constructs a value of the
specified type given the expression list. If the expression list is a
single expression, the type conversion expression is equivalent (in
definedness, and if defined in meaning) to the corresponding cast
expression (5.4). If the type specified is a class type, the class
type shall be complete. If the expression list specifies more than a
single value, the type shall be a class with a suitably declared
constructor (8.5, 12.1), and the expression T(x1, x2, ...) is
equivalent in effect to the declaration T t(x1, x2, ...); for some
invented temporary variable t, with the result being the value of t as
a prvalue.
所以不管优化与否,它们在标准上是等价的。
请注意,这与前面提到的其他答案是一致的。只是为了正确起见,引用了标准的内容。
First grouping: it depends on what A_factory_func returns. The first line is an example of copy initialization, the second line is direct initialization. If A_factory_func returns an A object then they are equivalent, they both call the copy constructor for A, otherwise the first version creates an rvalue of type A from an available conversion operators for the return type of A_factory_func or appropriate A constructors, and then calls the copy constructor to construct a1 from this temporary. The second version attempts to find a suitable constructor that takes whatever A_factory_func returns, or that takes something that the return value can be implicitly converted to.
第二组:逻辑完全相同,只是内建类型没有任何奇异构造函数,因此它们实际上是相同的。
Third grouping: c1 is default initialized, c2 is copy-initialized from a value initialized temporary. Any members of c1 that have pod-type (or members of members, etc., etc.) may not be initialized if the user supplied default constructors (if any) do not explicitly initialize them. For c2, it depends on whether there is a user supplied copy constructor and whether that appropriately initializes those members, but the members of the temporary will all be initialized (zero-initialized if not otherwise explicitly initialized). As litb spotted, c3 is a trap. It's actually a function declaration.
就这部分回答:
A c2 = A();c3 (());
由于大多数答案都是c++11之前的,我补充了c++11必须说的:
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6)
followed by a parenthesized expression-list constructs a value of the
specified type given the expression list. If the expression list is a
single expression, the type conversion expression is equivalent (in
definedness, and if defined in meaning) to the corresponding cast
expression (5.4). If the type specified is a class type, the class
type shall be complete. If the expression list specifies more than a
single value, the type shall be a class with a suitably declared
constructor (8.5, 12.1), and the expression T(x1, x2, ...) is
equivalent in effect to the declaration T t(x1, x2, ...); for some
invented temporary variable t, with the result being the value of t as
a prvalue.
所以不管优化与否,它们在标准上是等价的。
请注意,这与前面提到的其他答案是一致的。只是为了正确起见,引用了标准的内容。
值得注意的是:
[12.2/1]类类型的临时对象可以在不同的上下文中创建:…在一些初始化中(8.5)。
例如,用于复制初始化。
[12.8/15]当满足某些条件时,允许实现省略类对象的复制构造…
换句话说,一个好的编译器不会在可以避免的情况下创建副本进行复制初始化;相反,它将直接调用构造函数——即,就像直接初始化一样。
换句话说,复制初始化就像在大多数<opinion>的情况下直接初始化,其中已经编写了可理解的代码。由于直接初始化可能会导致任意(因此可能是未知的)转换,我更喜欢在可能的情况下总是使用复制初始化。(额外的是,它实际上看起来像初始化。)</opinion>
技术血淋淋的景象:
[12.2/1接续以上]即使避免了临时对象的创建(12.8),也必须遵守所有的语义限制,就像创建了临时对象一样。
很高兴我不是在写c++编译器。