Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Если я правильно понял, ваш вызов

    g(f());

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

    g(f(), p);

из-за объявления

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

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