std::string::c_str()一生吗?

时间:2022-07-20 22:26:28

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.

谢谢你!

6 个解决方案

#1


70  

The c_str() result becomes invalid if the std::string is 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.

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

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 char pointers.)

在示例中,似乎可以安全地使用c_str()的结果,因为在该范围内,字符串没有被修改。(但是,我们不知道use_foo()或~Foo()会对这些值做什么;如果它们把字符串复制到其他地方,那么它们应该做一个真正的复制,而不仅仅是复制char指针。

#2


21  

Technically your code is fine.

严格地说,你的代码很好。

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

#3


6  

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

它是有效的,直到以下情况之一发生在相应的字符串对象:

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

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

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

#4


4  

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

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

#5


3  

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

从c_str()返回的const char*仅在下一次对std::string对象的非const调用之前有效。在这种情况下,您很好,因为您的std::string仍然在Foo的生存期范围内,并且您没有执行任何其他操作,在使用Foo时更改字符串。

#6


2  

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()修改字符串,则定义了实现。

#1


70  

The c_str() result becomes invalid if the std::string is 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.

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

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 char pointers.)

在示例中,似乎可以安全地使用c_str()的结果,因为在该范围内,字符串没有被修改。(但是,我们不知道use_foo()或~Foo()会对这些值做什么;如果它们把字符串复制到其他地方,那么它们应该做一个真正的复制,而不仅仅是复制char指针。

#2


21  

Technically your code is fine.

严格地说,你的代码很好。

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

#3


6  

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

它是有效的,直到以下情况之一发生在相应的字符串对象:

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

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

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

#4


4  

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

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

#5


3  

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

从c_str()返回的const char*仅在下一次对std::string对象的非const调用之前有效。在这种情况下,您很好,因为您的std::string仍然在Foo的生存期范围内,并且您没有执行任何其他操作,在使用Foo时更改字符串。

#6


2  

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()修改字符串,则定义了实现。