Reputation: 102
I am working with a C function that takes a string (i.e. a pointer to a null terminated array of char) and does stuff with it internally. It does not, however, keep a reference to the string after the function returns.
I want to pass it some formatted input, so I am using a std::stringstream
. In order to keep my code cleaner -- and because this pattern repeats throughout the codebase, I want to simply pass ss.str().c_str()
.
To me this seems scary because I'm calling a method on the temporary ss.str()
, but I think it's ok because of lifetime extension. Namely, the standard says:
A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call [...] In all these cases, the temporaries created during the evaluation of the expression initializing the reference, except the temporary to which the reference is bound, are destroyed at the end of the full-expression in which they are created and in the reverse order of the completion of their construction.
(emphasis mine)
As such, I would expect my values to stick around until the C API call ends. Am I mistaken? Is this safe to do? Conceptually, my code looks as follows:
void g(int x, int y) {
std::stringstream ss;
ss << "(" << x << ", " << y << ")";
puts(ss.str().c_str());
}
Upvotes: 2
Views: 635
Reputation: 234725
Yes that's fine, and ss.str().c_str()
crops up quite often when working with C-style APIs.
Informally speaking, the anonymous temporary std::string
returned from ss.str()
survives the puts()
function call. This means that the const char*
pointer returned by c_str()
remains valid for the duration of puts()
.
What you can't do is:
const char* ub = ss.str().c_str();
puts(ub);
as the pointer ub
is dangling.
Upvotes: 4