81

Is the following C++ code well-formed?

void consumer(char const* p) { std::printf("%s", p); } std::string random_string_generator(); consumer(random_string_generator().c_str()); 

The problem I have with it is, that after creating the temporary std::string object and taking the c_str() pointer, nothing prevents the std::string object from getting destroyed, unless I'm wrong.

Is this code well-formed according to the standard? It does work, when I test with g++.

3 Answers 3

102

The pointer returned by std::string::c_str() points to memory maintained by the string object. It remains valid until a non-const function is called on the string object, or the string object is destructed. The string object you're concerned about is a temporary. It will be destructed at the end of the full expression, not before and not after. In your case, the end of the full expression is after the call to consumer, so your code is safe. It wouldn't be if consumer saved the pointer somewhere, with the idea of using it later.

The lifetime of temporaries has been strictly defined since C++98. Before that, it varied, depending on the compiler, and the code you've written wouldn't have worked with g++ (pre 1995, roughly—g++ changed this almost immediately when the standards committee voted it). (There wasn't an std::string then either, but the same issues affect any user written string class.)

Sign up to request clarification or add additional context in comments.

4 Comments

what if one used the c_str() const char* in a subsequent statement (still inside the function, but outside the first statement)? Would this bring us a dangling pointer?
I answer myself... In that case it would be invalid: § 12.2 ... Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created. This is true even if that evaluation ends in throwing an exception.
std::string temp = random_string_generator().c_str(); Is this correct to assume temp would be correct? since the life time of the string returned from random_string_generator() will be till the end of expression?
@AyushPant, yes. The const char* is valid when initializing temp which copies the characters. But why not just move the string returned by the function?
28

The temporary std::string's lifetime extends just beyond the point where consumer returns, so it is safe to use anything on that string directly from within consumer. What is not OK is to store the value that c_str returns and try to use it later (the temporary will have been destroyed, and we can only guess what you will find at the other end of the pointer).

4 Comments

can you provide a hint as regards the C++03 or the C++11 standard please?
The lifetime of a temporary is defined in §12.2. (Section 12 is entitled "Special member functions", which isn't exactly where you'd expect to look for lifetime of temporaries, but that's where it is.)
@user1095108 and lifetime of function arguments can be obtained from §3.2.2 and §3.7.2 in the c++03 standard.
To save someone from a debugging nightmare, note that I have seen an older arm-gcc variant in c++11 mode seeming to not handle this correctly. If I invoke a function foo((std::string("bar") + std::to_string(4)).c_str()) with a function foo(std::string x) then it crashes the program. Somehow the temporary result of the addition isn't kept throughout the function call. At least that's what I'm gathering, since removing the c_str() call fixes the issue I am seeing.
7

The temporary returned by the function random_string_generator() can be used in consumer() function safely.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.