什么是std :: string :: c_str()生命周期?

在我的一个程序中,我必须与一些与const char*一起工作的遗留代码进行交互。

比方说,我有一个像这样的结构:

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

我的高级应用程序只处理std::string ,所以我想用std::string::c_str()来取回const char*指针。

但是c_str()的生命周期是多less?

我可以做这样的事情,而不面临未定义的行为?

 { 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 } 

或者我应该立即复制c_str()的结果到另一个地方?

谢谢。

如果std::string被销毁,或者调用了string的非const成员函数,则c_str()结果将变为无效。 所以,如果你需要保留它的话,通常你会想做一个副本。

在你的例子中,看起来c_str()的结果是安全使用的,因为在那个范围内string没有被修改。 (但是,我们不知道use_foo()use_foo()可能会用这些值做什么;如果它们将string复制到其他地方,那么它们应该做一个真正的拷贝 ,而不是复制char指针。

技术上你的代码是好的。

但是你已经写了这样一个方法,使得不知道代码的人很容易被打破。 对于c_str(),唯一安全的用法是将其作为parameter passing给函数。 否则,你会打开自己的维修问题。

例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 } 

所以维护很明显:

更好的scheme:

 { // 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); } 

但是,如果你有conststring,你并不需要它们:

 { char const* server = "my_server"; char const* name = "my_name"; Foo foo; foo.server = server; foo.name = name; use_foo(foo); } 

好。 出于某种原因,你希望他们作为string:
为什么不在通话中使用它们:

 { 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()); } 

直到相应的string对象出现以下情况之一才有效:

  • 该对象被破坏
  • 该对象被修改

除非在将c_str() s复制到foo但在use_foo()之前修改了这些string对象,否则您的代码可以正常工作。

c_str()的返回值仅在下一次调用同一个string的非常数成员函数时才有效

只要string不被破坏或修改,使用c_str()就可以了。 如果string被修改使用先前返回的c_str()定义了实现。

c_str()返回的const char*只有在对std::string对象的下一个非const调用之前才有效。 在这种情况下,你很好,因为你的std::string仍然在Foo的生命周期的范围内,而且你没有做任何其他的操作,在使用foo时会改变string。