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 指针? [复制]

使用 std::string.c_str() 作为另一个方法的参数时的段错误

C++ 中的 StringStream/c_str() 损坏