支持的init列表中的对象创建顺序 [英] Object creation order in braced init list

查看:120
本文介绍了支持的init列表中的对象创建顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  #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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆