Reputation: 891
In the below code snippet... is it safe to store a reference to the temporary string returned by Quote::toXML
in ToXML::s_
member variable, at least as long as it is used with the <<
operator only? I.e. is the result of the sub-expression q.toXML
alive until the next ;
?
And what is the full expression here w.r.t. the return value of q.toXML
. The entire std::cout
or the call to ToXML
constructor ?
#include <iostream>
#include <string>
struct ToXML
{
ToXML(char const * const tag, std::string const & s) : tag_(tag), s_(s)
{
}
char const * tag_;
std::string const & s_;
};
std::ostream & operator << (std::ostream & os, ToXML const & v)
{
return os << "<" << v.tag_ << ">" << v.s_ << "</" << v.tag_ << ">";
}
struct Quote
{
std::string toXML() const
{
return "<Quote/>";
}
};
int main()
{
Quote q;
std::cout << ToXML("quote", q.toXML()) << std::endl;
return 0;
}
Upvotes: 2
Views: 108
Reputation: 302767
Yes, it is safe.
From [class.temp]:
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. [...]
The second context is when a reference is bound to a temporary.117 The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
— A temporary object bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
We're in that bullet point. The temporary object is bound to a reference parameter (s
) and persists until the completion of the full-expression containing the call. That is, it persists until
std::cout << ToXML("quote", q.toXML()) << std::endl;
// --- here ---------------------------------------^
Since it lasts throughout its usage, it is perfectly safe. However, as soon as you do something like:
ToXML x("quote", q.toXML());
you're stuck with a dangling reference, so I would use this pattern sparingly.
Upvotes: 2