When you write a function this way ...
const S& f(int i) const { std::cout << i << "\n"; return *this; }
... you instruct the compiler to return const S& , and you take the responsibility of ensuring that the object referenced has a lifetime suitable for the use of the caller. (“collateral” may be documentation of client use that works correctly with your design.)
Often - with a typical separation of the code into headers and implementation files - the f(int) const implementation will not even be visible to the calling code, and in such cases the compiler has no idea which reference S can be returned to, and also that S is temporary or not, so he has no reason to decide on the need to extend his life.
Besides the obvious options (for example, trusted clients for writing safe code, return by value, or a smart pointer), you should know about a more obscure option ...
const S& f(int i) const & { ...; return *this; } const S f(int i) const && { ...; return *this; }
& and && just before the function bodies overload f so that the && version is used if *this is movable, otherwise the & version is used. Thus, someone linking const & to f(...) called by the expiring object is bound to a new copy of the object and extends the life of the local const link, while the object does not expire (yet) the const link will be to the original object (which is still not guaranteed live until the link - some caution is required).
Tony delroy
source share