Что такое std::string:: C str() lifetime?
в одной из моих программ, я должен взаимодействовать с некоторым старым кодом, который работает с 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()
в другое место ?
спасибо.
6 ответов:
The
c_str()
результат становится недействительным, еслиstd::string
уничтожается или если вызывается неконстантная функция-член строки. Так что, как правило, вы хотите, чтобы сделать копию его, если вам нужно держать его вокруг.в случае вашего примера, похоже, что результаты
c_str()
используются безопасно, потому что строки не изменяются в то время как в этой области. (Однако мы не знаем, чтоuse_foo()
или~Foo()
может делать с этими значениями; если они копируют строки в другом месте, тогда они должны сделать истинный скопировать, а не просто копироватьchar
указатели.)
технически ваш код в порядке.
но вы написали таким образом, что делает его легко сломать кого-нибудь, кто не знает код. Для 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()); }