Ich habe zwei neue Fragen:
1) Betrachte diese Zeile:
%Vor%Es gab zwei Dinge, die ich gelernt habe, aber ich möchte eine Bestätigung: Wie ich gelernt habe, zeigt die Nachricht "alloc" an, dass die Instanz von NSString im "Heap" Speicher gespeichert wird. Ich habe auch verstanden, dass primitive Variablen wie "chars" im "stack" Speicher gespeichert sind.
Bedeutet das:
Die zweite Frage ist direkt verwandt und verursacht für mich ein persönliches Dilemma (wahrscheinlich weil ich einen Punkt verpasse): 2) Welchen der beiden Ansätze würdest du konsultieren und warum ?:
%Vor%Wenn meine erste Frage bestätigt wird, sollten beide Ansätze "am Ende" auf Zeichen zeigen, die im Stapelspeicher gespeichert sind. Ich sehe daher eigentlich nicht den Zweck, die erste Option zu verwenden und sich um die Retain-Zählung zu kümmern.
Kurze Antwort: In diesem Fall haben beide Zeilen das gleiche Ergebnis. Es ist in Ordnung, die String-Konstante direkt myString
zuzuweisen.
Längere Antwort:
Es stimmt, dass Objective-C-Objekte auf dem Heap zugewiesen sind. Es ist jedoch nicht wahr, dass "primitive" Werte immer auf dem Stapel gespeichert sind. Lokale Variablen werden auf dem Stapel gespeichert, unabhängig davon, ob sie primitiv sind oder nicht. (Sie können zum Beispiel eine lokale Variable deklarieren, die eine Struktur ist, die nicht als primitiv betrachtet wird.) Sie können Grundwerte auf dem Heap speichern, aber die einzige Möglichkeit, in diesem Fall auf sie zuzugreifen, ist über einen Zeiger. Zum Beispiel:
%Vor%Der Grund, dass wir immer Zeiger verwenden, um auf Objective-C-Objekte zu verweisen, ist, dass Objekte immer auf dem Heap zugewiesen werden. Wenn Sie etwas auf dem Stapel speichern möchten, muss der Compiler seine Größe kennen. In Objective-C ist die Größe eines Objekts nicht bekannt, bis das Programm tatsächlich ausgeführt wird.
Also, zurück zu deinen Strings. Versuchen Sie, die folgenden zwei Zeilen auszuführen:
%Vor% Wenn Sie nach der zweiten Zeile brechen, finden Sie, dass foo
und bar
die gleiche Adresse enthalten; Das heißt, sie zeigen auf dasselbe Objekt. Da NSString-Objekte unveränderlich sind, wird beim Erstellen eines Objekts mit einer konstanten Zeichenfolge nur ein Zeiger auf diese Konstante zurückgegeben.
Warum gibt es sogar einen -initWithString:
in NSString, wenn das alles ist? NSString ist ein "Klassencluster", was bedeutet, dass NSString die öffentliche Schnittstelle zu mehreren verschiedenen internen Klassen ist. Wenn Sie einen NSString *, der keine Konstante ist, an -initWithString:
übergeben, ist das zurückgelieferte Objekt möglicherweise eine Instanz einer anderen Klasse als die, die Sie erhalten, wenn Sie die Konstante verwenden. Als Klassencluster versteckt NSString eine Menge von Implementierungsdetails von Ihnen, so dass Sie eine gute Leistung für verschiedene Stringtypen erhalten, ohne sich darum kümmern zu müssen, wie alles funktioniert.
NSString
s sind interessant, weil sie bis vor kurzem der einzige Typ von Objective-C-Objekten waren, die als Literal bereitgestellt werden konnten. Die Blockobjekte, die in iOS 4 und OS X 10.6 hinzugefügt wurden, sind die anderen neueren Erweiterungen, die mir bekannt sind, aber sie haben ihre eigenen besonderen Regeln, weshalb ich das nur der Vollständigkeit halber erwähne.
C-Primitive können im Heap oder im Stack gespeichert werden. Zum Beispiel:
%Vor% Die meisten Objective-C-Objekte können nur auf dem Heap gespeichert werden. Sie haben recht damit zu sagen, dass alloc
eine neue Kopie eines Objekts auf dem Heap liefert, und das Ergebnis Ihres Aufrufs myString
besteht darin, einen Zeiger auf einen NSString auf dem Heap zu haben.
Die Syntax @""
ist jedoch eine Abkürzung für das Erstellen eines Objekts. @"Value"
erstellt tatsächlich ein Objektliteral. So könnten Sie beispielsweise Folgendes tun:
Und die Ausgabe wäre "alue". Sie können die Nachricht substringFromIndex:
an @"Value"
senden, da es sich um ein literales Objekt handelt.
Was NSString
mit initWithString:
genau macht ist eine Implementierung, aber Sie können sicher sein, dass es eine Kopie der Sache braucht, auf die verwiesen wird, wenn es nötig ist. Sonst würden Sie seltsames Verhalten sehen, wenn Sie so etwas tun würden:
Sie brauchen sich also keine Gedanken über die Lebensdauer von allem zu machen, was Sie ihm übergeben. Es ist NSString
's Job, damit umzugehen.
In der Praxis laufen NSString
Objektliterale niemals wirklich ab, so dass der Punkt ein wenig unklar ist. Wenn Sie jedoch initWithUTF8String:
oder etwas anderes verwendet hätten, das ein C-Literal verwendet und das C-Literal auf dem Stapel war, müssten Sie sich trotzdem keine Sorgen machen, weil NSString
damit umgehen würde.
Als Antwort auf Ihre zweite Frage würde ich die zweite Version bevorzugen, weil sie kürzer ist und daher deutlicher zeigt, was Sie vorhaben. Es gibt einige theoretische Leistungsvorteile für Letzteres - insbesondere, wenn Sie an mehreren Stellen das gleiche Literal verwenden - aber sie sind so unglaublich vernachlässigbar, dass sie heutzutage nicht in Betracht gezogen werden sollten.
Tags und Links memory objective-c nsstring theory