在我的一个程序中,我必须与一些使用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条答案
按热度按时间jum4pzuy1#
如果
std::string
被破坏或者调用了字符串的非常数成员函数,那么c_str()
的结果就无效了。所以,如果你需要保存它,通常你会想做一个副本。在您的示例中,
c_str()
的结果似乎被安全地使用了,因为字符串在该作用域中没有被修改。(但是,我们不知道use_foo()
或~Foo()
可能对这些值做了什么;如果他们将字符串复制到其他地方,那么他们应该执行真正的 * 复制 *,而不仅仅是复制char
指针。)evrscar22#
从技术上讲,您的代码没有问题。
但是您的编写方式很容易让不懂代码的人破解。对于c_str(),唯一安全的用法是将其作为参数传递给函数。否则,您将面临维护问题。
例一:
因此,对于维护来说,要使其显而易见:
更好的解决方案:
但是如果你有const字符串,你实际上并不需要它们:
好吧。出于某种原因,你想把它们当作字符串:
为什么不用它们只在呼叫:
bq9c1y663#
在Map的
string
对象发生下列其中一种情况之前,它一直有效:除非在将
c_str()
复制到foo
之后,但在调用use_foo()
之前修改这些string
对象,否则您的代码没有问题。rxztt3cl4#
c_str()的返回值只有在下一次为同一字符串调用非常数成员函数之前才有效
cyvaqqii5#
从
c_str()
返回的const char*
只在下一次对std::string
对象的非常数调用之前有效。在这种情况下,你没有问题,因为你的std::string
在Foo
的生存期内仍然在作用域中,而且你在使用foo时没有做任何其他会改变字符串的操作。1mrurvl16#
只要字符串没有被破坏或修改,使用c_str()是可以的。如果字符串被修改,使用先前返回的c_str()是实现定义的。
3htmauhk7#
为了完整起见,这里有一个reference and quotation from cppreference.com:
从
c_str()
获得的指针可以通过以下方式无效:string
上呼叫非常数成员函式,不包括operator[]
、at()
、front()
、back()
、begin()
、rbegin()
、end()
和rend()
。