CString Aufklärung
-
Rio1 schrieb:
ich würde mal gerne wissen was bei der zuweisung passiert:
CString s1; CString s2; s2="hallo"; s1 = s2;wird hier nur der Pointer an s1 gegeben oder wird s2 in s1 kopiert (ich glaub hab ich irgendwo gelesen)
Hier wird der Inhalt kopiert (CString ist eine Klasse mit eigenem Copy-Ctor und op=).
und was passiert hier:
CString s1; char* s2; wchar_t s3[20]; s2 = new char[20]; s2 = "test2"; s3="test3"; s1 = s2; s1 = s3; delete[] s2;gleiche Frage wie oben Pointer übergabe oder Copy?
"s2="test2";" erzeugt ein Speicherleck und verbiegt lediglich einen Zeiger (danach kommst du nicht mehr auf den mit new[] angeforderten Speicherbereich), "s3="test3";" dürfte dir schon der Compiler um die Ohren hauen.
(Zeichen-Arrays kopierst du mit strcpy())
Und von den beiden Zuweisungen "s1=...;" dürfte je nach deinen UNICODE-Definitionen nur eine erlaubt sein (aber wenigstens kopiert die dann die Daten).
Und was passiert in diesem falle:
//deklaration: void useString(CString s1);useString(s3);wird nun in der funktion s3 in s1 kopiert oder nur die Pointer übergeben?
freigabe s1 am ende der Funktion?useString("Hallo"); // Konstante angelegt in s1?Das legt jeweils den String s1 bei Aufruf an und kopiert in dessen Speicher die Daten aus s3 bzw. den Text "Hallo".
und wie verhält sich das ganze mit CString als Rückgabewerten in Funktionen
//deklaration: CString GetString();CString GetString() { CString s1; s1="Hallo" return s1; }CString s2; s2 = GetString();geht sowas? und was passiert intern (also wird bevor s1 aufgelöst wird s1 in s2 kopiert?)
der Rückgabewert von GetString() bleibt noch solange gültig, bis die Anweisung "s2=GetString()" abgearbeitet wurde - und innerhalb dieser Anweisung kopiert sich s2 die Rückgabedaten in einen eigenen Speicherbereich.
(btw, ich bin mir nicht ganz sicher, wie oft die Daten auf dem Weg kopiert werden)Was will mir die MSDN damit sagen:
This assignment (=) operator reinitializes an existing CString object with new data. If the destination string — that is, the left side — is already large enough to store the new data, no new memory allocation is performed. Be aware that memory exceptions may occur whenever you use the assignment operator because new storage is often allocated to hold the resulting CString object.
Jeder CString verwaltet intern einen Speicherbereich für seine Daten. Wenn der übergebene String kleiner ist als dieser Bereich, werden die Daten einfach überschrieben. Wenn nicht, gibt er den Bereich frei, holt sich einen neuen (entsprechend größeren) Bereich und füllt diesen (und wenn diese Anforderung schiefgeht - BUMM!).
-
danke für die detailierte Antwort.
CString erstellt bei = immer einen neuen String.. Dabei kann char* und wchar_t* automatisch in einen CString konvertiert werden...
richtig?
-
Fast - CString arbeitet afaik ENTWEDER mit char ODER mit wchar_t, aber nicht mit beidem gemischt.
-
ok, danke. Aber wie sieht es aus wenn ich ein wchar_t* habe und diesen statt 20 später auf 30 erhöhen möchte. Ist das dynamisch möglich?
wchar_t* z;
z = new wchar[20];
int i = 30;
// hier z auf [i] erhöhen;
delete[] z;
-
Ja, aber das mußt du fast von Hand erledigen (und dir die bisherige Größe mitschreiben):
int size = 20; char* data = new char[size+1];//Platz für den Null-Terminator ... char* tmp = new char[nsize+1];//größeres Array holen memcpy(tmp,data,min(size+1,nsize));tmp[nsize]='\0';//Daten kopieren delete[]data; data=tmp;Aber besser ist es, du nimmst eine fertige Containerklasse, die sich um solche Details kümmert (z.B. CString oder std::string/std::wstring).
-
geht das auch irgendwie mit malloc? ich möchte ja nicht den char* nochmal neu anlegen sondern nur erweitern...
-
Ich habe eure Antworten nur überflogen...
Zu deiner ersten Frage:CString s1; CString s2; s2="hallo"; s1 = s2;Hier wird an s1 nur der Zeiger von s2 weitergegeben. Erst wenn du s1 oder s2 änderst wird wirklich eine Kopie erstellt. Siehe auch Reference Counting.
-
Hier wird an s1 nur der Zeiger von s2 weitergegeben. Erst wenn du s1 oder s2 änderst wird wirklich eine Kopie erstellt. Siehe auch Reference Counting.
Bist du dir richtig sicher? s2 wird ja nicht bei der deklararion zugewiesen, sondern wird ja schon geändert (nach der Dekl.)
Also sieht für mich nach Copy aus oder?
-
Ja ich bin mir sicher. Bei der Zuweisung
s1 = s2wird zunächst der Zeiger des internen Buffers von s1 einfach auf die Adresse vom internen Buffer von s2 gesetzt. Wenn man danach einen der beiden ändert wird eine Kopie erstellt. Was davor passiert ist egal.
-
das gilt aber nur für 2 CStrings. Die Zuweisung eines wchar_t* oder char* erzwingt wohl immer ein COPY oder?
-
ja.
Beis2="hallo";wird natürlich kopiert.
-
vielen Dank!
Grüße Rio.