函数参数的评估顺序

如果一个函数有多个参数,则未指定它们的评估顺序。下面的代码可以打印 x = 1, y = 2x = 2, y = 1,但未指定哪个。

int f(int x, int y) {
    printf("x = %d, y = %d\n", x, y);
}
int get_val() {
    static int x = 0;
    return ++x;
}
int main() {
    f(get_val(), get_val());
}

Version >= C++ 17

在 C++ 17 中,函数参数的评估顺序仍未指定。

但是,每个函数参数都被完全评估,并且在任何函数参数之前保证调用对象。

struct from_int {
  from_int(int x) { std::cout << "from_int (" << x << ")\n"; }
};
int make_int(int x){ std::cout << "make_int (" << x << ")\n"; return x; }

void foo(from_int a, from_int b) {
}
void bar(from_int a, from_int b) {
}

auto which_func(bool b){
  std::cout << b?"foo":"bar" << "\n";
  return b?foo:bar;
}

int main(int argc, char const*const* argv) {
  which_func( true )( make_int(1), make_int(2) );
}

这必须打印:

bar
make_int(1)
from_int(1)
make_int(2)
from_int(2)

要么

bar
make_int(2)
from_int(2)
make_int(1)
from_int(1)

在任何 makefrom 之后它可能无法打印 bar,它可能无法打印:

bar
make_int(2)
make_int(1)
from_int(2)
from_int(1)

或类似的。在 C++ 17 之前,在 make_ints 之后打印 bar 是合法的,就像在做任何 from_int 之前做两个 make_ints 一样。