函数参数和默认参数的评估顺序

时间:2022-11-05 11:12:10

I recently ran across the following situation:

我最近碰到了以下情况:

#include <iostream>

int *p = 0;

int f() {
    p = new int(10);
    return 0;
}

void g(int x, int *y = p) {
    std::cout << y << std::endl;
}

int main() {
    g(f());
}

This is quite subtle, since you usually don't expect the default arguments to change during their evaluation for the function call. I had to take a look at the assembly to spot this error.

这非常微妙,因为在评估函数调用期间,通常不希望默认参数发生变化。我不得不看一下程序集来发现这个错误。

Now my question is: Is this really undefined behavior, since there aren't any guarantees concerning the evaluation order of function arguments?

现在我的问题是:这是否真的是未定义的行为,因为对函数参数的评估顺序没有任何保证?

2 个解决方案

#1


15  

The order of evaluation (i.e. determining the value) of function arguments is not specified. The compiler is free to execute them in any order, and even intermingled if there are no other factors stopping it from doing so.

未指定函数参数的评估顺序(即确定值)。编译器可以按任何顺序*执行它们,如果没有其他因素阻止它这样做,甚至可以混合使用。

Evaluation of default arguments happens in the context of the caller, not the callee. So the call to f() is necessary for one argument, and reading the global variable p for the other. Which order this happens in is not specified, so the global could be read before or after the call to f().

默认参数的评估发生在调用者的上下文中,而不是被调用者。因此,对一个参数调用f()是必要的,并为另一个参数读取全局变量p。未指定发生这种情况的顺序,因此可以在调用f()之前或之后读取全局。

#2


13  

If I understand it correctly, your call

如果我理解正确,你的电话

    g(f());

is equivalent to

相当于

    g(f(), p);

due to the declaration

由于声明

    void g(int x, int *y = p);

And arguments to the g function , f() and p, can be evaluated in any order, so you can get g called with y assigned either zero (if p is evaluated first, then it returns its initial value) or the newly allocated array pointer (if f() is evaluated first and it assigns a new value to p as its side effect).

并且g函数f()和p的参数可以按任何顺序进行计算,因此你可以使用y指定为零(如果首先计算p,然后返回其初始值)或新分配的数组指针(如果首先计算f(),它将一个新值赋给p作为其副作用)。

#1


15  

The order of evaluation (i.e. determining the value) of function arguments is not specified. The compiler is free to execute them in any order, and even intermingled if there are no other factors stopping it from doing so.

未指定函数参数的评估顺序(即确定值)。编译器可以按任何顺序*执行它们,如果没有其他因素阻止它这样做,甚至可以混合使用。

Evaluation of default arguments happens in the context of the caller, not the callee. So the call to f() is necessary for one argument, and reading the global variable p for the other. Which order this happens in is not specified, so the global could be read before or after the call to f().

默认参数的评估发生在调用者的上下文中,而不是被调用者。因此,对一个参数调用f()是必要的,并为另一个参数读取全局变量p。未指定发生这种情况的顺序,因此可以在调用f()之前或之后读取全局。

#2


13  

If I understand it correctly, your call

如果我理解正确,你的电话

    g(f());

is equivalent to

相当于

    g(f(), p);

due to the declaration

由于声明

    void g(int x, int *y = p);

And arguments to the g function , f() and p, can be evaluated in any order, so you can get g called with y assigned either zero (if p is evaluated first, then it returns its initial value) or the newly allocated array pointer (if f() is evaluated first and it assigns a new value to p as its side effect).

并且g函数f()和p的参数可以按任何顺序进行计算,因此你可以使用y指定为零(如果首先计算p,然后返回其初始值)或新分配的数组指针(如果首先计算f(),它将一个新值赋给p作为其副作用)。