A
Darüber kann man freilich streiten. Die fehlende const-correctness in bezug auf Delphi tritt aber nur bei den vom Delphi-Compiler generierten Headerdateien explizit in Erscheinung. Die EMUVCL-Klassen wie String, Currency, Set, Variant und dergleichen sind nicht automatisch generiert worden, sondern werden von manuell entwickelt und gepflegt. Besonders dann, wenn eine Memberfunktion c_str(), data() oder swap() heißt und somit eindeutig ein C++-Idiom erfüllt, kann man vermutlich davon ausgehen, daß diese Schnittstelle bewußt definiert wurde. Daß c_str() keinen const-Zeiger zurückgibt, ist mit großer Sicherheit kein Versehen.
Über den Grund dafür kann ich nur spekulieren, aber ich halte es für nicht unwahrscheinlich, daß die semantische Parallele zu WideString::c_bstr(), das einen nicht konstanten WideString-Zeiger zurückgibt und auf ein COM-BSTR-Objekt verweist, gewahrt werden sollte. Dabei stellt sich natürlich die Frage, ob die COM-Unterstützung und der WideString-Typ (in Delphi erst ab Version 3) in C++Builder seit Anbeginn - die erste Version fiel zeitlich und technisch zwischen Delphi 2 und 3 - vorhanden war, denn ansonsten wäre dieser Kausalzusammenhang natürlich fragwürdig
Edit: Ich muß obige Behauptung revidieren. Auf dem Heimweg fiel mir ein, daß du in gewisser Weise doch recht hast - nämlich sind die String-Typen von Delphi (ausgenommen WideString, das einfach einen BSTR wrappt) über copy-on-write implementiert, und die c_str()-Methode gibt, wie du sagst, einen Zeiger auf den internen Puffer zurück. Anders als der operator [] aber ruft c_str () nicht Unique() auf, somit ist es möglich, über den darunterliegenden Puffer unbemerkt auch andere Strings zu verändern, die noch auf denselben Puffer verweisen. (Allerdings halte ich das für einen Bug in c_str().)
In meiner Anwendung tritt das zwar nicht ein, da ich mindestens mit dem Aufruf von SetLength() garantiert einen nur einfach referenzierten String habe, aber sicherheitshalber und zur Förderung der Konsistenz sollte man es dennoch anders handhaben:
void foo (void)
{
String s;
s.SetLength (200);
unsigned len = GetAString (&s[1], s.Length () + 1 /* including '\0' */);
s.SetLength (len);
if (len > s.Length ()) // more than 200 characters
GetAString (s.c_str (), len + 1);
}
(Wann wird das Forum eigentlich von diesem bedauernswürdigen Server mit einem bestimmt zweiminütigen Ping auf eine etwas aktuellere Maschine migriert?)