我只知道i = i++;
是未定义的行为,但是如果在表达式中调用了两个或更多函数,并且所有函数都相同。是未定义吗?例如:
int func(int a)
{
std::cout << a << std::endl;
return 0;
}
int main()
{
std::cout << func(0) + func(1) << std::endl;
return 0;
}
答案 0 :(得分:12)
表达式func(0) + func(1)
的行为定义为结果将是通过使用参数func
和0
调用func
获得的结果的总和参数1
。
但是,调用函数的顺序可能是implementation dependent,尽管可能未指定。也就是说,编译器可以生成相当于的代码:
int a = func(0);
int b = func(1);
int result = a + b;
或者它可以生成:
int a = func(1);
int b = func(0);
int result = a + b;
除非func
具有取决于通话顺序的副作用,否则通常不会出现问题。
答案 1 :(得分:3)
std::cout << func(0) + func(1) << std::endl;
函数调用func(0)
或func(1)
是否先执行,取决于实现。之后,有一个序列点,输出func(0) + func(1)
。
但根据定义,它不称为未定义行为。
答案 2 :(得分:3)
如果我们查看undefined部分1.9
计划执行段落,此计划的行为不是unspecified,而是draft C++ standard 15 说(强调我的):
除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的评估是不合理的。 [注意:在程序执行期间不止一次评估的表达式中,不需要在不同的评估中一致地执行对其子表达式的未序列和不确定顺序的评估。 -end note]运算符操作数的值计算在运算符结果的值计算之前排序。如果对标量有副作用 对于相同标量对象的另一个副作用或使用相同标量对象的值进行值计算,对象未被排序,行为未定义。
如果我们检查5.7
添加运算符部分,其中包含+
和-
该部分未指定排序,则会对其进行排序。
在这种情况下,func
会产生副作用,因为它输出到stdout
,因此输出的顺序将取决于实现,甚至可能会随后进行评估。
请注意,;
结束表达式语句,部分6.2
表达式语句表示:
[...]表达式语句中的所有副作用都在下一个语句执行之前完成。[...]
因此虽然未指定函数调用的顺序,但每个语句的副作用在下一个之前完成。