Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the lifetime of the result of std::string::c_str()?

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.

like image 812
ereOn Avatar asked Jun 23 '11 15:06

ereOn


People also ask

What does string c_str return?

The c_str method of std::string returns a raw pointer to the memory buffer owned by the std::string .

What is the purpose of the c_str () member function of 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.

How does c_str () work?

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).

What does filename c_str () mean?

See this. The c_str() member function returns a const char * pointer to the string.


2 Answers

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.)

like image 149
Kristopher Johnson Avatar answered Oct 21 '22 15:10

Kristopher Johnson


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()); } 
like image 44
Martin York Avatar answered Oct 21 '22 13:10

Martin York