支持的init列表中的对象创建顺序 [英] Object creation order in braced init list
问题描述
#include< iostream>
struct A
{
A(){std :: cout< (A :: A); }
};
struct B
{
B(){std :: cout< (B :: B); }
};
struct C
{
template< typename ... Args>
C(Args&& ...){}
};
int main(int agrc,char * argv [])
{
C {A(),B()}; //< - prints(B :: B)(A :: A)
std :: cout< std :: endl;
C {(A(),B())}; //< - prints(A :: A)(B :: B)
std :: cout< std :: endl;
return 0;
}
我有两个问题:
- 为什么在第一个支撑的init列表对象是从右到左的顺序创建的?
- 为什么括号会在第二种情况下还原此订单?
编辑: with msvs 2013
在第二个实例中,你实际上只是初始化 B / code>;通过使用逗号运算符,
A()
被构造并首先丢弃。
C {(A(),B())};
// | ^^^^^^^^^^ |
// \ --------> (A(),B())
// ^^^ ^^^
// | |
// / \
//评估,THEN评估,
//丢弃使用
另一方面,在第一个例子中,你正在初始化 C
> 临时表通过初始化器列表,其元素也应该从左到右评估,但是你的编译器在这方面是有问题的:
< blockquote>
[C ++ 11:8.5.4 / 4]:
在 initializer-list em> braced-init-list ,初始化子句(包括包扩展(14.5.3),的所有结果)按出现的顺序进行求值。 也就是说,与给定的 initializer-clause 相关联的每个值计算和副作用在与任何 initializer-clause 相关联的每个值计算和副作用之前排序在 initializer-list 的逗号分隔列表中跟随它。 [注意:此评估顺序无论初始化的语义如何都保持;例如,当将 initializer-list 的元素解释为构造函数调用的参数时,即使通常对调用的参数没有排序约束,它也适用。
我可以用GCC 4.8 * ,但Clang 3.5行为正确† 。该问题已在‡ 之前的 std-discussion 列表中讨论过,但是我还没有找到一个GCC Bugzilla ID § 。
C {A(),B()};
// ^^^ ^^^
// | \
// eval- THEN
//已使用
// \ /
// \ /
//两者都使用
* http://coliru.stacked-crooked.com/a/1f18e0d1f8973f3c
† http://coliru.stacked-crooked.com/a/5a6e7506e9be97c3
‡ https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TQUnBFkUBDg
§ #51253 可能相关。#include <iostream> struct A { A() { std::cout << "(A::A)"; } }; struct B { B() { std::cout << "(B::B)"; } }; struct C { template<typename ...Args> C(Args && ...) {} }; int main(int agrc, char *argv[]) { C {A(), B()}; // <-- prints (B::B)(A::A) std::cout << std::endl; C {(A(), B())}; // <-- prints (A::A)(B::B) std::cout << std::endl; return 0; }
I've got 2 questions:
- Why in first braced init list objects are created in right-to-left order?
- Why parentheses in second case revert this order?
Edit: I've compiled it with msvs 2013
In the second instance, you're actually only initialising with B()
; through the use of the comma operator, A()
was constructed and thrown away first.
C {(A(), B())};
//|^^^^^^^^^^|
// \--------> (A(), B())
// ^^^ ^^^
// | |
// / \
// evaluated, THEN evaluated,
// discarded used
On the other hand, in the first instance, you're initialising the C
from both temporaries through an initializer list, whose elements should also be evaluated left-to-right, as it happens, but your compiler is buggy in this regard:
[C++11: 8.5.4/4]:
Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. —end note ]
I can reproduce the problem with GCC 4.8*, but Clang 3.5 behaves properly†. The bug has been discussed on the std-discussion list before‡, but I haven't found a GCC Bugzilla ID yet§.
C {A(), B()};
// ^^^ ^^^
// | \
// eval- THEN
// uated evaluated
// \ /
// \ /
// both used
* http://coliru.stacked-crooked.com/a/1f18e0d1f8973f3c
† http://coliru.stacked-crooked.com/a/5a6e7506e9be97c3
‡ https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/TQUnBFkUBDg
§ #51253 may be related.
这篇关于支持的init列表中的对象创建顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!