什么是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。