如果我正确理解了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警告不正确:
警告:对&#39; i&#39;进行多次无序修改[-Wunsequenced]
并打印:1 2 3
gcc也警告说:
警告:'i'上的操作可能未定义[-Wsequence-point]
并打印:3 3 3
哪个输出正确?
答案 0 :(得分:0)
根据C ++ 17 5.2.2 / 4中的注释,函数参数的初始化未被排序:
调用函数时,应初始化每个参数(8.3.5)(8.5,12.8,12.1)及其对应的参数 论点。 [注意:这种初始化相对于彼此不确定地排序(1.9) - 结束说明]
这意味着即使函数参数保证从左到右进行评估(我无法在C ++ 17草案中找到任何信息),参数的初始化仍然是不确定的顺序。
这意味着,例如,如果您的参数都调用相同的复制构造函数,而后者又修改了全局/静态资源,则您的程序具有未指定的行为:
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
}
一个好的编译器会在发现依赖于未指明的行为=确定性但未记录的行为时给出警告,你不能假设这些行为。