Когда вы пишете функцию таким образом ...
const S& f(int i) const { std::cout << i << "\n"; return *this; }
... вы инструктируете компилятор вернуть const S&
и берете на себя ответственность за обеспечение того, чтобы указанный объект имел время жизни, подходящее для использования вызывающей стороной. («обеспечение» может означать документирование использования клиента, которое правильно работает с вашим дизайном.)
Часто - с типичным разделением кода на заголовки и файлы реализации - реализация f(int) const
даже не будет видна вызывающему коду, и в таких случаях компилятор не понимает, какой S
ссылка может быть возвращена, и является ли эта S
временный или нет, поэтому у него нет оснований для принятия решения о том, нужно ли продлевать срок службы.
Помимо очевидных вариантов (например, доверие клиентам писать безопасный код, возврат по значению или интеллектуальный указатель), стоит знать о более неясном варианте ...
const S& f(int i) const & { ...; return *this; }
const S f(int i) const && { ...; return *this; }
&
и &&
непосредственно перед телами функций перегружают f
, так что используется версия &&
, если *this
является перемещаемым, в противном случае используется версия &
. Таким образом, кто-то, привязывающий const &
к f(...)
, вызванный к истекающему объекту, будет привязан к новой копии объекта и продлит время жизни в соответствии с локальной const
ссылкой, в то время как, когда объект не истекает (пока), ссылка const
будет к исходному объекту (который по-прежнему не гарантирован, пока действует ссылка - требуется некоторая осторожность).
person
Tony Delroy
schedule
01.09.2015
f
возвращает lvalue, а не prvalue. - person Kerrek SB   schedule 01.09.2015S()
заканчивается в конце полного оператора. - person Jarod42   schedule 01.09.2015f
слева от=
. - person αλεχολυτ   schedule 01.09.2015f
возвращает lvalue, потому что его объявленный тип возвращаемого значенияT &
для некоторого не ссылочного типаT
(а именноT = const S
). - person Kerrek SB   schedule 01.09.2015