Object creation order in braced init list

后端 未结 3 1460
情书的邮戳
情书的邮戳 2021-01-08 00:40
#include 

struct A
{
    A() { std::cout << \"(A::A)\"; }
};

struct B
{
    B() { std::cout << \"(B::B)\"; }
};

struct C
{
    templat         


        
相关标签:
3条回答
  • 2021-01-08 00:54

    It is an old bug of gcc 4.8.1 ( I suppose you use GCC) or of other compiler. I wrote about this bug several months ago the initializer-list: a bug of GCC 4.8.1

    Though it is written in Russian but you can translate it into English using for example google service translate.

    As it was said by others elements of the initializer-list are evaluated from left to right and all side effects are applied before evaluation of the next element.

    In your second code example you in fact call the constructor with one expression that is an expression of the comma operator. The comma operator in fact behaves the same way as initializer-lists that is it evaluates its operands from left to right and applies side effects before evaluation of the next operand.

    0 讨论(0)
  • 2021-01-08 01:08

    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.

    0 讨论(0)
  • 2021-01-08 01:08

    Why in first braced init list objects are created in right-to-left order?

    No. It is left-to-right. Your compiler has bug which is why it is evaluating right-to-left. GCC (4.8) is known to have this bug. Do you use GCC?

    Why parentheses in second case revert this order?

    Same. Left to right. In this case, comma operator comes into picture, which evaluates operands left-to-right.

    0 讨论(0)
提交回复
热议问题