Welche Lebensdauer hat das Ergebnis von std::string::c_str()?

Lesezeit: 4 Minuten

Welche Lebensdauer hat das Ergebnis von stdstringc str
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::stringalso 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.

  • 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 die const char* lebt nicht ewig, sondern bis die Saite zerstört wird

    – Etwas etwas

    2. Dezember 2014 um 17:34 Uhr


Welche Lebensdauer hat das Ergebnis von stdstringc str
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.)

  • Der c_str()-Zeiger könnte ungültig sein, wenn das std::string-Objekt ein automatisches Objekt ist, das den Gültigkeitsbereich verlässt oder eine Thread-Erstellungsfunktion aufruft.

    – GuruM

    16. Oktober 2012 um 15:49 Uhr


  • Kannst du bitte Erklären non-const member function of the string is called.?

    – Mathew Kurian

    24. Dezember 2013 um 11:03 Uhr

  • Eine “nicht konstante Member-Funktion” ist jede Member-Funktion, die nicht mit gekennzeichnet ist const Stichwort. Eine solche Funktion könnte den Inhalt des Strings ändern, in diesem Fall muss der String möglicherweise den Speicher für die nullterminierte Version des zurückgegebenen Strings neu zuweisen c_str(). Zum Beispiel, size() und length() sind constsodass Sie sie aufrufen können, ohne sich Gedanken über die Änderung der Zeichenfolge machen zu müssen, aber clear() ist nicht const.

    – Christoph Johnson

    24. Dezember 2013 um 20:16 Uhr


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.

1646907010 292 Welche Lebensdauer hat das Ergebnis von stdstringc str
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 stringausschließlich operator[], at(), front(), back(), begin(), rbegin(), end() und rend().

987490cookie-checkWelche Lebensdauer hat das Ergebnis von std::string::c_str()?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy