Порядок оценки аргументов функции и аргументов по умолчанию

недавно я столкнулся со следующей ситуацией:

#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());
}

Это довольно тонко, так как вы обычно не ожидаете, что аргументы по умолчанию изменятся во время их оценки для вызова функции. Я должен был взглянуть на сборку, чтобы обнаружить эту ошибку.

теперь мой вопрос: это действительно неопределенное поведение, так как нет никаких гарантий относительно порядка оценки аргументов функции?

2 ответов


порядок оценки (т. е. определения значения) аргументов функции не указан. Компилятор может выполнять их в любом порядке и даже смешивать, если нет других факторов, препятствующих этому.

оценка аргументов по умолчанию происходит в контексте вызывающего абонента, а не абонент. Таким образом, вызов f() необходим для одного аргумента, а чтение глобальной переменной p для другого. В каком порядке это происходит в не указывается, так может быть прочитан до или после вызова f ().


если я правильно понял, ваш звонок

    g(f());

эквивалентно

    g(f(), p);

из-за декларации

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

и аргументы в пользу , f() и p, могут быть оценены в любом порядке, так что вы можете получить g позвонил с y назначено либо ноль (если p сначала вычисляется, затем возвращается его начальное значение) или вновь выделенный указатель массива (если f() сначала оценивается и присваивается новый значение p как свой побочный эффект).