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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6456359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:11:05  来源:igfitidea点击:

What is std::string::c_str() lifetime?

c++stringcstring

提问by ereOn

In one of my programs, I have to interface with some legacy code that works with const char*.

在我的一个程序中,我必须与一些与const char*.

Lets say I have a structure which looks like:

假设我有一个看起来像的结构:

struct Foo
{
  const char* server;
  const char* name;
};

My higher-level application only deals with std::string, so I thought of using std::string::c_str()to get back const char*pointers.

我的更高级别的应用程序只处理std::string,所以我想使用std::string::c_str()来获取const char*指针。

But what is the lifetime of c_str()?

但是生命周期是c_str()多少?

Can I do something like this without facing undefined behavior ?

我可以在不面对未定义行为的情况下做这样的事情吗?

{
  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
}

Or am I supposed to immediately copy the result of c_str()to another place ?

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

Thank you.

谢谢你。

采纳答案by Kristopher Johnson

The c_str()result becomes invalid if the std::stringis destroyed or if a non-const member function of the string is called. So, usually you will want to make a copy of it if you need to keep it around.

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

In the case of your example, it appears that the results of c_str()are used safely, because the strings are not modified while in that scope. (However, we don't know what use_foo()or ~Foo()might be doing with those values; if they copy the strings elsewhere, then they should do a true copy, and not just copy the charpointers.)

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

回答by Martin York

Technically your code is fine.

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

BUTyou have written in such a way that makes it easy to break for somebody that does not know the code. For c_str() the only safe usage is when you pass it as a parameter to a function. Otherwise you open yourself up-to maintenance problems.

但是你写的方式很容易让不知道代码的人破解。对于 c_str() 唯一安全的用法是将其作为参数传递给函数时。否则,您将面临维护问题。

Example 1:

示例 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
}

So for maintenance make it obvious:

因此,对于维护而言,显而易见:

Better solution:

更好的解决方案:

{
  // 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);    
}

But if you have const strings you don't actually need them:

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

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

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

  use_foo(foo);
}

OK. For some reason you want them as strings:
Why not use them only in the call:

好的。出于某种原因,您希望它们作为字符串:
为什么不只在调用中使用它们:

{
  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());
}

回答by sharptooth

It is valid until one of the following happens to the corresponding stringobject:

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

  • the object is destroyed
  • the object is modified
  • 对象被销毁
  • 对象被修改

You're fine with your code unless you modify those stringobjects after c_str()s are copied into foobut before use_foo()is called.

除非string在将c_str()s 复制到之后foo但在use_foo()调用之前修改这些对象,否则您的代码没问题。

回答by DumbCoder

Return value of c_str() is valid only until the next call of a nonconstant member function for the same string

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

回答by AJG85

The const char*returned from c_str()is only valid until the next non-const call to the std::stringobject. In this case you're fine because your std::stringis still in scope for the lifetime of Fooand you aren't doing any other operations that would change the string while using foo.

const char*返回了c_str()才有效,直到下一个非const调用std::string对象。在这种情况下,你很好,因为你std::string的生命周期仍然在范围内,Foo并且你没有做任何其他操作会在使用 foo 时更改字符串。

回答by Victor Sergienko

For completeness, here's a reference and quotation from cppreference.com:

为了完整起见,这里有来自 cppreference.com参考和引用

The pointer obtained from c_str()may be invalidated by:

  • Passing a non-const reference to the string to any standard library function, or
  • Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end()and rend().

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

  • 将字符串的非常量引用传递给任何标准库函数,或
  • 上主叫非const成员函数string,不包括operator[]at()front()back()begin()rbegin()end()rend()

回答by CharlesB

As long as the string isn't destroyed or modified, using c_str() is OK. If the string is modified using a previously returned c_str() is implementation defined.

只要字符串没有被破坏或修改,使用 c_str() 就可以了。如果使用先前返回的 c_str() 修改字符串是实现定义的。