Может ли вторая ссылка Const продлить срок службы временного
- Фон:
Я заметил, что подпись std::max:
шаблон
const T& max(const T&, const T&);
и я задавался вопросом о последствиях возвращения ссылки на const T...
Если мы передадим два L-значения, то имеет смысл вернуть ссылку на одно из двух. Но если мы передадим две PR-значения, что возвращается и безопасно ли это использовать?
Проблема:
Я говорил с некоторыми коллегами, и вот минимальный рабочий пример проблемы: http://cpp.sh/4en4
#include <iostream>
int glob = 100;
class temp{
int* val;
public:
temp(int n = 0){
val = new int(n);
}
void print() const{ std::cout << "I store " << *val << std::endl; }
~temp(){
std::cout << "temp object died" << std::endl;
delete val;
val = &glob;
}
};
const temp& foo(const temp& a){
return a;
}
int main(){
const temp& b = foo(2);
std::cout << "Is it safe?" << std::endl;
b.print();
}
Без оптимизации:
временный объект умер Это безопасно? Я храню 100
С умеренным:
временный объект умер Это безопасно? Я храню -1992206527
Запуск этого с разными уровнями оптимизации дает разные результаты. Однако во всех случаях возврат ссылки не продлевает время жизни локального объекта; его дескриптор по-прежнему вызывается, хотя в одном случае мы, кажется, восстанавливаем ссылку на уничтоженный объект, а в другом мы, кажется, имеем висячий указатель.
Стандарт:
Цитирование из стандарта C++, номер документа N4618:
12.2 пункт 6:
... когда ссылка связана с временным. Временный объект, к которому привязана ссылка, или временный объект, являющийся полным объектом подобъекта, к которому привязана ссылка, сохраняется в течение всего времени существования ссылки, за исключением:
(6.1) - Временный объект, связанный с опорным параметром в вызове функции (5.2.2), сохраняется до завершения полного выражения, содержащего вызов.
(6.2) - Срок действия временной привязки к возвращенному значению в операторе возврата функции (6.6.3) не продлевается; временное уничтожается в конце полного выражения в операторе возврата. "
Из (6.1) может показаться, что временный foo (2) должен существовать для всего оператора, который инициализирует b.
Из (6.2) может показаться, что локальное "а" уничтожается, что фактически уничтожает временный foo(2), в результате чего b принимает разрушенное значение.
Мои вопросы:
1a. Что такое полное выражение, которое содержит временную сгенерированную foo(2)
в const temp& b = foo(2);
1б. Может ли вторая ссылка const продлить срок службы временного?
- Почему std::max реализован как таковой, учитывая очевидную опасность?