In one of my programs, I have to interface with some legacy code that works with const char*
.
Lets say I have a structure which looks like:
struct Foo
{
const char* server;
const char* name;
};
My higher-level application only deals with std::string
, so I thought of using std::string::c_str()
to get back const char*
pointers.
But what is the lifetime of c_str()
?
Can I do something like this without facing undefined behavior ?
{
std::string server = "my_server";
std::string name = "my_name";
Foo foo;
foo.server = server.c_str();
foo.name = name.c_str();
// We use foo
use_foo(foo);
// Foo is about to be destroyed, before name and server
}
Or am I supposed to immediately copy the result of c_str()
to another place ?
Thank you.
For completeness, here's a reference and quotation from cppreference.com:
The
const char*
returned fromc_str()
is only valid until the next non-const call to thestd::string
object. In this case you're fine because yourstd::string
is still in scope for the lifetime ofFoo
and you aren't doing any other operations that would change the string while using foo.As long as the string isn't destroyed or modified, using c_str() is OK. If the string is modified using a previously returned c_str() is implementation defined.
The
c_str()
result becomes invalid if thestd::string
is destroyed or if a non-const member function of the string is called. So, usually you will want to make a copy of it if you need to keep it around.In the case of your example, it appears that the results of
c_str()
are used safely, because the strings are not modified while in that scope. (However, we don't know whatuse_foo()
or~Foo()
might be doing with those values; if they copy the strings elsewhere, then they should do a true copy, and not just copy thechar
pointers.)Technically your code is fine.
BUT you have written in such a way that makes it easy to break for somebody that does not know the code. For c_str() the only safe usage is when you pass it as a parameter to a function. Otherwise you open yourself up-to maintenance problems.
Example 1:
So for maintenance make it obvious:
Better solution:
But if you have const strings you don't actually need them:
OK. For some reason you want them as strings:
Why not use them only in the call:
It is valid until one of the following happens to the corresponding
string
object:You're fine with your code unless you modify those
string
objects afterc_str()
s are copied intofoo
but beforeuse_foo()
is called.