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.
The c_str method of std::string returns a raw pointer to the memory buffer owned by the std::string .
std::string::c_strReturns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
The c_str() method converts a string to an array of characters with a null character at the end. The function takes in no parameters and returns a pointer to this character array (also called a c-string).
See this. The c_str() member function returns a const char * pointer to the string.
The c_str()
result becomes invalid if the std::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 what use_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 the char
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:
{ std::string server = "my_server"; std::string name = "my_name"; Foo foo; foo.server = server.c_str(); foo.name = name.c_str(); // // Imagine this is a long function // Now a maintainer can easily come along and see name and server // and would never expect that these values need to be maintained as // const values so why not re-use them name += "Martin"; // Oops now its broken. // We use foo use_foo(foo); // Foo is about to be destroyed, before name and server }
So for maintenance make it obvious:
Better solution:
{ // Now they can't be changed. std::string const server = "my_server"; std::string const name = "my_name"; Foo foo; foo.server = server.c_str(); foo.name = name.c_str(); use_foo(foo); }
But if you have const strings you don't actually need them:
{ char const* server = "my_server"; char const* name = "my_name"; Foo foo; foo.server = server; foo.name = name; use_foo(foo); }
OK. For some reason you want them as strings:
Why not use them only in the call:
{ std::string server = "my_server"; std::string name = "my_name"; // guaranteed not to be modified now!!! use_foo(Foo(server.c_str(), name.c_str()); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With