诠释我= 0; foo(++i, ++i, ++i);定义明确?

int i=0; foo(++i, ++i, ++i); well defined?

如果我正确理解了 C++17 标准,那么函数参数的顺序应该是不确定的 (P0145R3)。 请考虑以下测试用例:

#include <stdio.h>
void foo(int a, int b, int c) { printf("%d %d %d\n", a, b, c); }
int main() {
  int i = 0;
  foo(++i, ++i, ++i);
}

clang 错误警告:

warning: multiple unsequenced modifications to 'i' [-Wunsequenced]

并打印:1 2 3

gcc 还警告:

warning: operation on ‘i’ may be undefined [-Wsequence-point]

并打印:3 3 3

哪个输出是正确的?

根据 C++17 5.2.2/4 中的注释,函数参数的初始化是无序的:

When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument. [ Note: Such initializations are indeterminately sequenced with respect to each other (1.9) — end note ]

这意味着即使保证函数参数是从左到右计算的(我在 C++17 草案中找不到任何相关信息),参数的初始化顺序仍然不确定。

意思是,例如,如果您的参数都调用相同的复制构造函数,这又会修改 global/static 资源,则您的程序具有未指定的行为:

static int f;

Foo::Foo (const Foo& foo)
  : x(f++)
{}

...

void func (Foo a, Foo b, Foo c)
{
  std::cout << a.x << b.x << c.x;  // unspecified output
}

一个好的编译器会在发现对未指定行为的依赖时发出警告 = 确定性但未记录的行为,您不能对此做出任何假设。