Страницы

Поиск по вопросам

суббота, 13 октября 2018 г.

Продление жизни значения константной ссылкой

Как известно, если rvalue передаётся в некую функцию через константную ссылку, то время его жизни продлевается. Т. е. в следующем примере оно точно живёт пока выполняется функция ref_to_ptr. Вопрос в том, насколько долго обязано жить такое значение и допустимо ли его использование в функции print, либо же это UB с разыменованием потенциально мусорного указателя?
https://ideone.com/CcacHz
#include
using namespace std;
template const T *ref_to_ptr(const T &x) { return &x; }
void print(const int *val) { cout << *val << endl; }
int main() { print(ref_to_ptr(42)); return 0; }


Ответ

Насколько я понимаю стандарт (цитата):
⁴ [...] Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created. [...] ⁵ There are three contexts in which temporaries are destroyed at a different point than the end of the full-expression. [...] ⁶ The third context is when a reference is bound to a temporary object. The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference [...] The exceptions to this lifetime rule are: (6.9) — A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call. (6.10) — The lifetime of a temporary bound to the returned value in a function return statement is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
Иными словами: обычно временный объект, на который ссылается ссылка, умирает вместе со ссылкой. Но если вы передаёте в функцию временный объект как аргумент для ref-параметра, время жизни этого временного объекта продлевается до конца всего выражения, содержащего вызов функции.
Это значит, что время жизни параметра x заканчивается в конце строки
print(ref_to_ptr(42));
то есть доступа к «умершему» объекту нет.
Это также, судя по всему, означает, что переписав код следующим образом:
const int *ptr = ref_to_ptr(42); print(ptr);
вы получите таки undefined behaviour, т. к. время жизни временного объекта, на который указывает ptr, заканчивается после первой строки!

Комментариев нет:

Отправить комментарий