Гарантирует ли стандарт C++11, что временный объект, переданный функции, будет уничтожен после завершения функции?
Как известно, этот стандарт C++11 гарантирует, что временный объект, переданный функции, будет создан до вызова функции: гарантирует ли стандарт C++11, что временный объект, переданный функции, будет создан до вызова функции?
Но гарантирует ли стандарт C++11, что временный объект, переданный в функцию, будет уничтожен после завершения функции (не раньше)?
Рабочий проект, Стандарт для языка программирования C++ 2016-07-12: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4606.pdf
§ 12.2 Временные предметы
§ 12.2 / 5
Существует три контекста, в которых временные объекты уничтожаются в другой точке, чем конец полного выражения. Первый контекст - это когда конструктор по умолчанию вызывается для инициализации элемента массива без соответствующего инициализатора (8.6). Второй контекст - это когда конструктор копирования вызывается для копирования элемента массива, когда копируется весь массив (5.1.5, 12.8). В любом случае, если конструктор имеет один или несколько аргументов по умолчанию, уничтожение каждого временного объекта, созданного в аргументе по умолчанию, выполняется до создания следующего элемента массива, если таковой имеется. Третий контекст - это когда ссылка связана с временным.
Также:
§ 1.9 / 10
Полное выражение - это выражение, которое не является подвыражением другого выражения. [Примечание: в некоторых контекстах, таких как неоцененные операнды, синтаксическое подвыражение считается полным выражением (раздел 5). - примечание к концу] Если языковая конструкция определена для создания неявного вызова функции, использование языковой конструкции считается выражением для целей этого определения. Вызов деструктора, сгенерированного в конце времени жизни объекта, отличного от временного объекта, является неявным полным выражением. Преобразования, применяемые к результату выражения для удовлетворения требований языковой конструкции, в которой появляется выражение, также считаются частью полного выражения.
Означает ли это, что стандарт C++11 гарантирует, что временный объект, переданный функции, будет уничтожен не до того, как функция завершится, а именно в конце полного выражения?
#include <iostream>
using namespace std;
struct T {
T() { std::cout << "T created \n"; }
int val = 0;
~T() { std::cout << "T destroyed \n"; }
};
void function(T t_obj, T &&t, int &&val) {
std::cout << "func-start \n";
std::cout << t_obj.val << ", " << t.val << ", " << val << std::endl;
std::cout << "func-end \n";
}
int main() {
function(T(), T(), T().val);
return 0;
}
Выход:
T created
T created
T created
func-start
0, 0, 0
func-end
T destroyed
T destroyed
T destroyed
Можем ли мы сказать, что T destroyed
всегда будет после func-end
?
И это:
function(T(), T(), T().val);
Всегда равно этому:
{
T tmp1; T tmp2; T tmp3;
function(tmp1, tmp2, tmp3.val);
}
1 ответ
Ну, вы уже процитировали весь текст, который говорит нам, что время жизни временного файла заканчивается в конце полного выражения. Так да, "T destroyed
"всегда будет последним.
Если бы разрушение не имело видимых побочных эффектов, то, по правилу "как будто", оно могло действительно произойти в любое время после этого… но это спорный вопрос, потому что, ну, это не было бы наблюдаемым.
Однако последние два фрагмента, которые вы представили, обычно не эквивалентны, потому что вы установили порядок построения / инициализации так, как это было раньше. Аргументы функции имеют неопределенный порядок оценки. Опять же, хотя, для этого конкретного T
Разница не заметна.