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

phl*_*psy 19 c++ operator-precedence undefined-behavior default-parameters

我最近碰到了以下情况:

#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());
}
Run Code Online (Sandbox Code Playgroud)

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

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

Seb*_*edl 15

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

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

  • @phlipsy参见[dcl.fct.default]/9"每次调用函数时都会计算默认参数.函数参数的评估顺序是未指定的.",我认为这显然意味着`g(f())`与`g(f(),p)`相同 (2认同)

Cia*_*Pan 13

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

    g(f());
Run Code Online (Sandbox Code Playgroud)

相当于

    g(f(), p);
Run Code Online (Sandbox Code Playgroud)

由于声明

    void g(int x, int *y = p);
Run Code Online (Sandbox Code Playgroud)

和参数的g功能,f()并且p可以以任意顺序进行评估,这样你就可以得到g调用y指定的要么是零(如果p是先进行计算,然后返回其初始值)或新分配的数组的指针(如果f()是第一次评估,它p为其副作用指定一个新值).