使用移动语义按初始值设定项列表顺序的未定义行为

时间:2019-06-26 20:36:12

标签: c++ c++11 move-semantics

是(1)个未定义的行为,还是始终首先评估该对中的第一个元素?

#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)
}

请注意,使用return make_pair(a, bar(std::move(a)));会有所不同吗?

1 个答案:

答案 0 :(得分:2)

您可能会看到evaluation order的规则。

  

10)在列表初始化中,给定初始化程序子句的每个值计算和副作用在与括号括起来的初始化程序列表中跟在其后的任何初始化程序子句相关的每个值计算和副作用之前进行排序。

所以

return { a, bar(std::move(a)) };
首先评估

a,然后评估bar(std::move(a))

  

请注意,使用return make_pair(a, bar(std::move(a)));会有所不同吗?

是的,这是一个函数调用,并且未指定求值顺序。它本身不是UB,但如果一个订单导致UB,则可以导致UB。 就您而言,这两个命令都很好,并且给出相同的结果。

C ++ 17进一步增加了该限制:

  

15)在函数调用中,相对于任何其他参数的值计算和副作用,每个参数初始化的值计算和副作用都不确定地排序。