诠释我= 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
}
一个好的编译器会在发现对未指定行为的依赖时发出警告 = 确定性但未记录的行为,您不能对此做出任何假设。
如果我正确理解了 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
}
一个好的编译器会在发现对未指定行为的依赖时发出警告 = 确定性但未记录的行为,您不能对此做出任何假设。