
ereOn
In einem meiner Programme muss ich eine Schnittstelle mit einem Legacy-Code herstellen, der damit funktioniert const char*
.
Nehmen wir an, ich habe eine Struktur, die wie folgt aussieht:
struct Foo
{
const char* server;
const char* name;
};
Meine übergeordnete Anwendung befasst sich nur mit std::string
also dachte ich an die Verwendung std::string::c_str()
zurück zu bekommen const char*
Zeiger.
Aber was ist die Lebensdauer von c_str()
?
Kann ich so etwas tun, ohne mit undefiniertem Verhalten konfrontiert zu werden?
{
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
}
Oder soll ich das Ergebnis gleich kopieren c_str()
an einen anderen Ort?
Danke.

Christoph Johnson
Die c_str()
Ergebnis wird ungültig, wenn die std::string
zerstört wird oder wenn eine nicht konstante Elementfunktion der Zeichenfolge aufgerufen wird. Normalerweise möchten Sie also eine Kopie davon erstellen, wenn Sie sie aufbewahren müssen.
Im Fall Ihres Beispiels scheinen die Ergebnisse von c_str()
werden sicher verwendet, da die Zeichenfolgen in diesem Bereich nicht geändert werden. (Allerdings wissen wir nicht, was use_foo()
oder ~Foo()
könnte mit diesen Werten zu tun haben; Wenn sie die Zeichenfolgen an eine andere Stelle kopieren, sollten sie ein wahres tun Kopierenund nicht nur kopieren char
Zeiger.)
Technisch ist Ihr Code in Ordnung.
ABER Sie haben so geschrieben, dass es für jemanden, der den Code nicht kennt, leicht zu knacken ist. Für c_str() ist die einzige sichere Verwendung, wenn Sie es als Parameter an eine Funktion übergeben. Sonst öffnen Sie sich Wartungsproblemen.
Beispiel 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
}
Machen Sie es also für die Wartung offensichtlich:
Bessere Lösung:
{
// 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);
}
Aber wenn Sie konstante Zeichenfolgen haben, brauchen Sie sie nicht wirklich:
{
char const* server = "my_server";
char const* name = "my_name";
Foo foo;
foo.server = server;
foo.name = name;
use_foo(foo);
}
OK. Aus irgendeinem Grund möchten Sie sie als Zeichenfolgen:
Warum nicht nur im Anruf verwenden:
{
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());
}
Es ist gültig, bis einer der folgenden Fälle mit dem entsprechenden passiert string
Objekt:
- das Objekt wird zerstört
- Das Objekt wird geändert
Sie sind mit Ihrem Code einverstanden, es sei denn, Sie ändern diese string
Gegenstände nach c_str()
s hineinkopiert werden foo
Aber vorher use_foo()
wird genannt.
Die const char*
zurückgekehrt von c_str()
gilt nur bis zum nächsten nicht konstanten Aufruf an die std::string
Objekt. In diesem Fall sind Sie in Ordnung, weil Ihr std::string
ist noch im Geltungsbereich für die Lebensdauer von Foo
und Sie führen keine anderen Operationen durch, die die Zeichenfolge ändern würden, während Sie foo verwenden.
Solange der String nicht zerstört oder modifiziert wird, ist die Verwendung von c_str() in Ordnung. Wenn die Zeichenfolge mit einem zuvor zurückgegebenen c_str() modifiziert wird, ist die Implementierung definiert.

Gemeinschaft
Der Vollständigkeit halber hier eine Referenz und Zitat von cppreference.com:
Der Zeiger erhalten von c_str()
kann ungültig werden durch:
- Übergeben einer nicht konstanten Referenz auf die Zeichenfolge an eine beliebige Standardbibliotheksfunktion oder
- Aufrufen von nicht konstanten Elementfunktionen auf der
string
ausschließlich operator[]
, at()
, front()
, back()
, begin()
, rbegin()
, end()
und rend()
.
9874900cookie-checkWelche Lebensdauer hat das Ergebnis von std::string::c_str()?yes
Ist mir passiert, als ich eine lokale Zeichenfolge in einer Funktion definiert und zurückgegeben habe
.c_str()
. Ich habe nicht verstanden, warum ich manchmal nur Teile der Zeichenfolge bekomme, bis ich verstanden habe, dass dieconst char*
lebt nicht ewig, sondern bis die Saite zerstört wird– Etwas etwas
2. Dezember 2014 um 17:34 Uhr