1

我只知道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;
}
4

3 回答 3

12

表达式的行为func(0) + func(1)被定义为结果将是通过func使用 的参数0func的参数调用获得的结果的总和1

但是,调用函数的顺序可能取决于实现,尽管它可能未指定。也就是说,编译器可以生成等效于:

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具有取决于调用顺序的副作用。

于 2013-09-20T01:08:14.080 回答
3
std::cout << func(0) + func(1) << std::endl;

是函数调用func(0)还是func(1)先执行,取决于实现。之后,有一个序列点,并被func(0) + func(1)输出。

但根据定义,它不称为未定义行为。

于 2013-09-20T01:10:02.507 回答
3

该程序的行为不是未定义的,而是未指定的,如果我们查看草案 C++ 标准部分1.9 程序执行15段说(强调我的):

除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值是未排序的。[注意:在程序执行期间多次评估的表达式中,其子表达式的未排序和不确定排序的评估不需要在不同的评估中一致地执行。—尾注] 运算符的操作数的值计算在运算符结果的值计算之前排序。如果标量对象上的副作用相对于同一标量对象上的另一个副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义。

如果我们检查覆盖的部分5.7 加法运算符+并且-该部分未指定排序,则它是无序的。

在这种情况下func,它会产生副作用,因为它正在输出stdout,因此输出的顺序将取决于实现,甚至可能会因后续评估而改变。

请注意,表达式语句的;结尾和表达式语句部分说:6.2

[...]表达式语句的所有副作用都在执行下一个语句之前完成。[...]

所以虽然函数调用的顺序是未指定的,但每条语句的副作用在下一条之前完成。

于 2013-09-20T02:05:02.840 回答