Какая стандартная формулировка говорит нам, что временное продление срока службы ref-to-const только «работает один раз»?

Мне был показан следующий пример в чате:

#include  struct foo { ~foo() { std::cout << "destroying!\n"; } }; const foo& func(const foo& a, const foo&) { return a; } int main() { foo x; const foo& y = func(foo(), x); std::cout << "main\n"; } 

Выход :

 destroying! main destroying! 

Похоже, что время жизни временного foo не распространяется на весь main , хотя оно привязано к ref-to- const в этой области.

Предположительно, тогда продление жизни только «работает один раз»; то есть он применяется, когда аргументы func инициализируются, но не передаются через последовательные привязки.

Является ли моя интерпретация правильной? Если это так (и если какой-либо отдельный параграф применим непосредственно), то какая стандартная формулировка определяет это поведение?

Это вопрос двух отчетов о проблемах: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299 и http://www.open-std.org/jtc1/sc22/ wg21 / docs / cwg_active.html # 1568 .

Первый отчет о проблеме, который я являюсь репортером, должен был охватывать все эти случаи, когда ссылка привязана к временному объекту, но не предназначена для продления срока службы. Описание в теле проблемы только упоминает, что prvalues ​​путают с временными выражениями (которые фактически решают, продлевается ли продолжительность жизни того, что они оценивают, или нет). Но lvalue и xvalues ​​также смешиваются с ними в Стандарте. Пример, где это происходит в контексте static_cast – номер выпуска № 1568 (в котором использование «временной переменной» еще больше смущает вопрос).

Собственно, это:

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

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

Ты почти прав. Такое поведение на самом деле происходит от вызова функции специально, а не из-за какого-либо правила «только работает один раз».

Вот формулировка для всей функции расширения продолжительности жизни, с соответствующим правилом, выделенным жирным шрифтом:

[C++11: 12.2/5]: [..] Временная привязка ссылки или временный объект, являющийся полным объектом подобъекта, к которому привязана ссылка, сохраняется для ресурса ссылки, за исключением :

  • [..]
  • Временная привязка к эталонному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.
  • [..]

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

Наверное, я немного замедлился, но для меня не стало ясно, каково решение этого вопроса от чтения других ответов. Таким образом, я изменил показанный код и хотел обобщить для других: ответ заключается в том, что вы получаете неопределенное поведение, если вы обращаетесь к y !

Запустите этот код:

 struct foo { int id; foo(int id) : id(id) { std::cout << "ctor " << id << std::endl; }; ~foo() { std::cout << "dtor " << id << std::endl; } }; const foo& func(const foo& a, const foo&) { return a; } int main(int argc, char** argv) { foo x(1); const foo& y = func(foo(2), x); std::cout << "main " << y.id << std::endl; return 0; } 

Выход для меня:

 ctor 1 ctor 2 dtor 2 main 2 dtor 1 

Но main 2 строка main 2 - это неопределенное поведение .

  • Когда имя массива или имя функции «преобразуется» в указатель? (в С)
  • Реализация CollectionChanged
  • Как рассчитать диапазон IP-адресов, когда заданы IP-адрес и сетевая маска?
  • Как работает эта функция шаблона «размер массива»?
  • Лямбда-выражения как параметры шаблона classа
  • Невозможно установить некоторые HTTP-заголовки при использовании System.Net.WebRequest
  • Оператор массива C ++ с несколькими аргументами?
  • Как вызвать код MATLAB с C?
  • Может ли FFmpeg использоваться в качестве библиотеки вместо автономной программы?
  • Как установить тайм-аут для строки кода c #
  • Почему частные поля являются приватными для типа, а не экземпляра?
  • Давайте будем гением компьютера.