函式引數的評估順序

如果一個函式有多個引數,則未指定它們的評估順序。下面的程式碼可以列印 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 一樣。