Intereting Posts
Стандартная компоновка и ссылки на C ++ Варианты для разработки classов с использованием безопасного downcasting Смещение элементов в массиве C ++ Каковы могут быть причины ошибки 0x80010108 (вызываемый объект отключился от своих клиентов)? перегрузка оператора для динамического массива, дающая странную ошибку Использование массива в функции – C Могу ли я специализировать шаблон classа с шаблоном псевдонимов? c ++ Fade между цветами? (Ардуин) Означает ли этот код облако точек о перекрестном продукте против часовой стрелки или по часовой стрелке? Указатели функций устройства CUDA в структуре без статических указателей или копий символов Ошибка наследования конструктора с boost :: multiprecision :: mpz_int Сохранение значения перед возвратом в переменную шум бурундука слишком мягкий Почему вводить концепцию для вывода типа спецификатора невозможно, если одно и то же ограничение должно выводить разные типы? Как захватить экран с помощью «подсказок»?

Почему ссылки на const ссылаются на продолжительность жизни rvalues?

Почему комитет C ++ решил, что ссылки на константы должны продлить время жизни временных рядов?

Этот факт уже широко обсуждался в Интернете, в том числе и в stackoverflow. Определенный ресурс, объясняющий, что это так, вероятно, это GoTW:

GotW # 88: Кандидат на “Наиболее важный const”

Каково было обоснование этой языковой функции? Известно ли это?

(Альтернативой было бы то, что время жизни временных рядов не распространяется на какие-либо ссылки.)


Моя собственная теория домашних животных для обоснования заключается в том, что это поведение позволяет объектам скрывать детали реализации. С помощью этого правила функция-член может переключаться между возвратом значения или константной ссылки на уже внутренне существующее значение без изменения кода клиента. Например, class матрицы может возвращать векторы строк и векторы столбцов. Чтобы свести к минимуму копии, один или другой может быть возвращен в качестве ссылки в зависимости от реализации (строка major или major major). Независимо от того, что нельзя вернуть по ссылке, необходимо вернуть, сделав копию и вернув это значение (если возвращаемые векторы смежны). Писатель библиотеки может захотеть, чтобы свобода изменила реализацию в будущем (значительная строка по сравнению с основным столбцом) и не позволяла клиентам писать код, который сильно зависит от того, является ли реализация главной строкой или столбцом. Попросив клиентов принять возвращаемые значения как const ref, матричный class может возвращать константы или значения без каких-либо изменений в код клиента. Независимо от того, известно ли первоначальное обоснование, я хотел бы это знать.

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

Тогда не было такой вещи, как RVO, поэтому просто запретить привязку временного к ссылке было бы хитом производительности.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf

Вы не ставите под сомнение, почему ссылки const ссылаются на временные, но просто на то, почему они продлевают время жизни этих временных рядов.

Рассмотрим этот код:

struct A { void foo() const; }; A bar(); const A& a = bar(); a.foo(); // (1) 

Если время жизни временного объекта, возвращаемого bar() не было расширено, любое использование символа (на примере строки (1)) приведет к неопределенному поведению. Это сделало бы привязки непараметрических константных ссылок к временным словам совершенно бесполезными.


EDIT (обращение к комментарию OP ):

Таким образом, реальный вопрос должен состоять в том, почему константная ссылочная переменная (которая не является параметром функции) позволяет привязываться к временному. Я не знаю оригинального обоснования для него ( ответ Ричарда Ходжеса может быть единственным истинным), но он дает нам одну полезную функцию. Учитывая следующий пример:

 struct B { virtual void foo() const; }; B bar(); const B& b = bar(); b.foo(); // (1) 

Единственное отличие этого примера от предыдущего состоит в том, что B::foo() является виртуальным. Теперь, что, если мы решили ввести новый class D в качестве подclassа B и изменить тип возврата bar() из B в D ?

 struct B { virtual void foo() const; }; struct D : B { virtual void foo() const; }; //B bar(); D bar(); const B& b = bar(); b.foo(); // This will call D::foo() // In the end the temporary bound by b will be correctly destroyed // using the destructor of D. 

Таким образом, привязка константных ссылок к временным рядам упрощает использование динамического polymorphismа для объектов, возвращаемых значением.