std::string::c_str() 结果的生命周期是多少?
Posted
技术标签:
【中文标题】std::string::c_str() 结果的生命周期是多少?【英文标题】:What is the lifetime of the result of std::string::c_str()? 【发布时间】:2011-09-21 07:57:19 【问题描述】:在我的一个程序中,我必须与一些适用于const char*
的遗留代码进行交互。
假设我有一个看起来像这样的结构:
struct Foo
const char* server;
const char* name;
;
我的高级应用程序只处理std::string
,所以我想到了使用std::string::c_str()
来取回const char*
指针。
但是c_str()
的生命周期是多少?
我可以做这样的事情而不会遇到未定义的行为吗?
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()
的结果复制到另一个地方?
谢谢。
【问题讨论】:
当我在函数中定义一个本地字符串并返回.c_str()
时发生在我身上。我不明白为什么有时我只得到字符串的一部分,直到我明白const char*
不会永远存在,但直到字符串被销毁
【参考方案1】:
只要字符串没有被破坏或修改,使用 c_str() 就可以了。如果使用先前返回的 c_str() 修改了字符串,则实现定义。
【讨论】:
【参考方案2】:c_str() 的返回值仅在下一次调用同一字符串的非常量成员函数之前有效
【讨论】:
【参考方案3】:在对应的string
对象发生以下一种情况之前有效:
除非您在将c_str()
s 复制到foo
之后但在调用use_foo()
之前修改那些string
对象,否则您的代码没有问题。
【讨论】:
【参考方案4】:如果std::string
被销毁或调用字符串的非常量成员函数,则c_str()
结果无效。所以,如果你需要保留它,通常你会想要复制它。
在您的示例中,c_str()
的结果似乎可以安全使用,因为在该范围内字符串不会被修改。 (但是,我们不知道 use_foo()
或 ~Foo()
可能会对这些值做什么;如果他们将字符串复制到其他地方,那么他们应该执行真正的复制,而不仅仅是复制char
指针。)
【讨论】:
c_str() 如果 std::string 对象是超出范围或调用线程创建函数的自动对象,则指针可能无效。 你能解释一下non-const member function of the string is called.
吗?
“非 const 成员函数”是任何未用 const
关键字标记的成员函数。这样的函数可能会改变字符串的内容,在这种情况下,字符串可能需要为c_str()
返回的字符串的空终止版本重新分配内存。例如size()
和length()
是const
,所以你可以调用它们而不用担心字符串改变,但clear()
不是const
。【参考方案5】:
从c_str()
返回的const char*
仅在下一次对std::string
对象的非常量调用之前有效。在这种情况下,您很好,因为您的 std::string
仍在 Foo
的生命周期内,并且您没有执行任何其他会在使用 foo 时更改字符串的操作。
【讨论】:
【参考方案6】:从技术上讲,您的代码没问题。
但是你写的方式很容易让不知道代码的人破解。对于 c_str() ,唯一安全的用法是将其作为参数传递给函数。否则,您将面临维护问题。
示例 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
所以为了维护让它显而易见:
更好的解决方案:
// 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);
但如果你有 const 字符串,你实际上并不需要它们:
char const* server = "my_server";
char const* name = "my_name";
Foo foo;
foo.server = server;
foo.name = name;
use_foo(foo);
好的。出于某种原因,您希望它们作为字符串: 为什么不只在通话中使用它们:
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());
【讨论】:
【参考方案7】:为了完整起见,这里是reference and quotation from cppreference.com:
从
将对字符串的非常量引用传递给任何标准库函数,或者 在c_str()
获得的指针可能会被以下行为无效:string
上调用非常量成员函数,不包括operator[]
、at()
、front()
、back()
、begin()
、rbegin()
、end()
和rend()
。李>
【讨论】:
以上是关于std::string::c_str() 结果的生命周期是多少?的主要内容,如果未能解决你的问题,请参考以下文章
深拷贝 std::string::c_str() 到 char * [重复]
std::string::c_str() 覆盖函数返回的前一个
C++string类型与C语言字符数组的转换 std::string.c_str()函数
为啥我仍然可以在字符串范围之外访问 std::string::c_str() 返回的 char 指针? [复制]