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

ere*_*eOn 92 c++ string cstring

在我的一个程序中,我必须与一些可用的遗留代码进行交互const char*.

可以说我的结构看起来像:

struct Foo
{
  const char* server;
  const char* name;
};
Run Code Online (Sandbox Code Playgroud)

我的高级应用程序只处理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
}
Run Code Online (Sandbox Code Playgroud)

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

谢谢.

Kri*_*son 81

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

对于您的示例,似乎c_str()安全地使用了结果,因为在该范围内不会修改字符串.(但是,我们不知道用这些值做什么use_foo()或者~Foo()可能做什么;如果他们将字符串复制到其他地方,那么他们应该做一个真正的副本,而不仅仅是复制char指针.)

  • "非const成员函数"是未使用`const`关键字标记的任何成员函数.这样的函数可能会改变字符串的内容,在这种情况下,字符串可能需要为`c_str()`返回的字符串的空终止版本重新分配内存.例如,`size()`和`length()`是`const`,所以你可以调用它们而不用担心字符串的变化,但是`clear()`不是`const`. (2认同)

Mar*_*ork 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
}
Run Code Online (Sandbox Code Playgroud)

所以对于维护来说,显而易见:

更好的方案:

{
  // 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);    
}
Run Code Online (Sandbox Code Playgroud)

但如果你有const字符串,你实际上并不需要它们:

{
  char const* server = "my_server";
  char const* name   = "my_name";

  Foo foo;
  foo.server = server;
  foo.name   = name;

  use_foo(foo);
}
Run Code Online (Sandbox Code Playgroud)

好.出于某种原因,你想要它们作为字符串:
为什么不在调用中使用它们:

{
  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());
}
Run Code Online (Sandbox Code Playgroud)


sha*_*oth 7

它有效直到相应string对象发生以下情况之一:

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

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