What is std :: string :: c_str () lifetime?

In one of my programs, I have to interact with some legacy code that works with const char* .

Suppose I have a structure that looks like this:

 struct Foo { const char* server; const char* name; }; 

My higher level application only deals with std::string , so I thought about using std::string::c_str() to return const char* pointers.

But what is the lifetime of c_str() ?

Can I do something like this without the appearance of undefined?

 { 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 should I immediately copy the result of c_str() to another location?

Thank.

+73
c ++ string cstring
Jun 23 2018-11-11T00:
source share
6 answers

The result of c_str() becomes invalid if std::string destroyed or the non-constant member function of the string is called. So usually you need to make a copy if you need to save it.

In the case of your example, it seems that the results of c_str() are used safely because the strings do not change during this area. (However, we do not know what use_foo() or ~Foo() can do with these values, if they copy strings elsewhere, then they should make a true copy, not just copy the char pointers.)

+64
Jun 23 2018-11-18T00:
source share

Technically, your code is fine.

BUT , you wrote in such a way that it was easy to break for someone who does not know the code. For c_str (), the only safe use is when you pass it as a parameter to a function. Otherwise, you will discover 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 this obvious:

The best decision:

 { // 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 constant strings, you really don't 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 to be like strings:
Why not use them only in a 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()); } 
+20
Jun 23 2018-11-11T00:
source share

It is valid if one of the following actions is performed on the corresponding string object:

  • object destroyed
  • object modified

Everything is fine with your code, unless you change those string objects after c_str() , copied to foo , but before calling use_foo() .

+6
Jun 23 2018-11-18T00:
source share

The return value of c_str () is valid only until the next invocation of a mutable member function for the same string

+4
Jun 23 2018-11-18T00:
source share

Until the line is destroyed or changed, the use of c_str () is fine. If the string was modified using the previously returned c_str (), then an implementation is implemented.

+2
Jun 23 2018-11-18T00:
source share

const char* returned with c_str() is valid only until the next non-constant call to the std::string object. In this case, you are fine, because your std::string is still in the scope of Foo and you are not doing any other operations that would change the string when using foo.

+2
Jun 23 2018-11-11T00:
source share



All Articles