Каков порядок уничтожения параметров функции?

Это продолжение моего предыдущего вопроса Каков порядок уничтожения аргументов функции? потому что я случайно перепутал аргументы с параметрами. Спасибо Коломбо и Т.С. за то, что избавил меня от терминологической путаницы в комментариях к этому вопросу.

Если тело некоторой функции f с параметрами p_1,..., p_n типов T_1,..., T_n соответственно выдает исключение, завершается или возвращает, то в каком порядке уничтожаются параметры и почему? Если возможно, дайте ссылку на стандарт.

Примеры:

template <typename ... Args>
void f(Args ... params) {} // in what order are params destroyed?

void f(T1 p1, T2 p2, T3 p3) {} // in what order are p1, p2 and p3 destroyed?

person jotik    schedule 02.05.2016    source источник
comment
Я не думаю, что создание исключения имеет большое значение в отношении порядка оценки.   -  person πάντα ῥεῖ    schedule 03.05.2016


Ответы (1)


Точный момент времени, когда параметры уничтожаются, не указан< /а>:

CWG решила не указывать, уничтожаются ли объекты параметров сразу после вызова или в конце полного выражения, к которому относится вызов.

Порядок, в котором строятся параметры, также не указан, но поскольку параметры функции имеют область действия блока, хотя порядок их построения не указан, уничтожение происходит в порядке, обратном построению. Например. рассмотреть возможность

#include <iostream>

struct A {
    int i;
    A(int i) : i(i) {std::cout << i;}
    ~A() {std::cout << '~' << i;} 
};

void f(A, A) {}

int main() {
    (f(0, 1), std::cout << "#");
}

печатает 10#~0~1 с GCC и 01#~1~0 с Clang; они создают параметры в разном порядке, но оба уничтожают в порядке, обратном построению, в конце полного выражения, в котором происходит вызов (а не сразу после возврата к вызывающей стороне). VC++ печатает 10~0~1#.

person Columbo    schedule 02.05.2016
comment
Есть ли какое-либо требование, чтобы порядок уничтожения был обратным порядку строительства? - person M.M; 03.05.2016
comment
@ M.M Я полагаю, что даже если бы этого не было, это было бы неявно необходимо, поскольку в противном случае это могло бы легко испортить вещи с RAII, например, вызвать тупиковую ситуацию с двумя удерживаемыми блокировками, которые не были сняты в правильном порядке. - person user541686; 03.05.2016
comment
@MM Возможно, так оно и есть на практике. Однако параметры не имеют автоматического срока хранения и не являются временными, поэтому я не могу найти никакого формального утверждения (и не понимаю, почему это было бы полезно). - person Columbo; 03.05.2016
comment
@M.M Имеет смысл, что это должно быть, поскольку между объектами могут быть зависимости, поэтому они должны быть уничтожены в порядке, обратном порядку их размещения. - person Nikos Kazazakis; 03.05.2016
comment
параметры не имеют автоматического срока хранения, да? - person T.C.; 03.05.2016
comment
@M.M Обратите внимание, что также можно ввести зависимости между параметрами после их построения во время выполнения тела. Как правило, это может быть неразумно, но... возможно, в некоторых случаях это оказывается практичным. - person jotik; 03.05.2016
comment
@Т.С. Длительность автоматического хранения AFAICS определяется тем, какие переменные области блока могут иметь, а какие параметры — нет. - person Columbo; 03.05.2016
comment
@Columbo Хм ... объем параметров функции описан в [basic.scope.block], а в других местах стандарта они явно считаются автоматическими (например, [class.copy]/31-32). - person T.C.; 03.05.2016
comment
@Т.С. Просто еще одна странность, я думаю. Во всяком случае, скорректировал ответ. - person Columbo; 03.05.2016
comment
Чтобы жизнь никогда не была скучной, MSVC печатает 10~0~1# (деструкторы вызываются из f). - person bogdan; 05.05.2016
comment
Встречается ли эта резолюция CWG в каком-либо стандарте или проекте? - person M.M; 11.05.2016
comment
@M.M Текущий статус находится в стадии разработки, поэтому в настоящее время разрабатывается соответствующая формулировка. - person Columbo; 11.05.2016
comment
@nikaza, если порядок построения или разрушения не определен, то установить зависимости невозможно. - person Jean-Baptiste Yunès; 13.05.2016
comment
Обновление: стандарт С++ 17 в конечном итоге сделал точку уничтожения (возврат против полного выражения) определяемой реализацией, а не неуказанной - person M.M; 17.03.2020
comment
stackoverflow.com/questions/39824814/ - person M.M; 17.03.2020