user10728479
user10728479

Reputation:

Undefined behaviour in initializer list order using move semantics

Is (1) undefined behavior, or is the first element of the pair always evaluated first?

#include <array>
#include <utility>

int bar(std::array<int, 3>&& ) {
    return 1;
}

std::pair<std::array<int, 3>, int> foo() {
    std::array<int, 3> a;
    return { a, bar(std::move(a)) };  // (1)
}

As a side note, would using return make_pair(a, bar(std::move(a))); instead be different?

Upvotes: 0

Views: 67

Answers (1)

Jarod42
Jarod42

Reputation: 217255

You might see the rule of evaluation order.

10) In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the brace-enclosed comma-separated list of initializers.

So for

return { a, bar(std::move(a)) };

a is firstly evaluated, then bar(std::move(a)).

As a side note, would using return make_pair(a, bar(std::move(a))); instead be different?

Yes, this is a function call, and order of evaluation is unspecified. it is not UB by itself, but can lead to UB if one order lead to UB. In your case both orders are fine and give same result.

C++17 adds that restriction moreover:

15) In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.

Upvotes: 2

Related Questions