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

时间:2011-06-23 15:12:25

标签: c++ string cstring

在我的一个程序中,我必须与一些与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()的结果复制到另一个地方?

谢谢。

7 个答案:

答案 0 :(得分:77)

如果c_str()被销毁或者字符串的非const成员函数被调用,std::string结果将变为无效。所以,如果你需要保留它,通常你会想要复制它。

对于您的示例,似乎安全地使用了c_str()的结果,因为在该范围内不会修改字符串。 (但是,我们不知道use_foo()~Foo()可能对这些值做了什么;如果他们将字符串复制到别处,那么他们应该执行真正的复制,并且不只是复制char指针。)

答案 1 :(得分:22)

从技术上讲,你的代码很好。

但是你这样写的方式让那些不知道代码的人容易打破。对于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());
}

答案 2 :(得分:7)

在相应的string对象发生以下情况之一之前有效:

  • 对象被销毁
  • 对象已修改

除非在将string复制到c_str()之后但在调用foo之前修改这些use_foo()个对象,否则您的代码就可以了。

答案 3 :(得分:4)

c_str()的返回值仅在下一次调用同一字符串的非常量成员函数之前有效

答案 4 :(得分:3)

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

答案 5 :(得分:2)

只要不销毁或修改字符串,使用c_str()就可以了。如果使用先前返回的c_str()修改了字符串,则执行定义。

答案 6 :(得分:1)

为完整起见,这里是reference and quotation from cppreference.com

  

c_str()获得的指针可能会因以下原因而失效:

     
      
  • 将对字符串的非常量引用传递给任何标准库函数,或者
  •   
  • string上调用非常量成员函数,但不包括operator[]at()front()back()begin(),{{ 1}},rbegin()end()
  •