2009-03-20 9 views
6

Dies ist eine Frage Anfänger, in der ich bin neugierig, ob dies eine gültige Verwendung eines Zeigers in einer Erklärung, wie ist:Ist dies eine gültige Verwendung eines Objective-C-Zeigers?

NSMutableDictionary *foo = [bar mutableCopy]; 

ich verwirrt, wenn diese gültig im Vergleich ist, wenn ich brauchen würde, Folgendes tun:

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0]; 
foo = [bar mutableCopy]; 
// use foo 
[foo release]; 

Sind beide gültig? Wann man eins über dem anderen benutzt?

Antwort

9

Wenn Sie sich fragen, warum Sie vielleicht verwirrt sind, möchte ich eine Erklärung hinzufügen, was das zweite Codebeispiel tatsächlich macht (und warum es nicht notwendig ist)).

Ich denke, Sie werden durch diese Linie verwirrt, weil diese Zeile oft als "Initializing Foo" beschrieben wird. Das ist ein bisschen irreführend. Dort werden technisch 2 verschiedene Entitäten geändert - das neue Objekt NSMutableDictionary wird angelegt und der Variablen "foo" wird ihre Adresse zugewiesen.

Die Linie erstellt tatsächlich ein neues Objekt NSMutableDictionary auf dem Heap (der dynamische Speicherbereich Ihrer Anwendung). Ich werde das "Wörterbuch 1" nennen. Damit dieses neue "Dictionary 1" -Objekt auf dem Heap gefunden werden kann, wird seine Speicheradresse in "foo" gespeichert. "foo" s Rolle ist, als ein Index zu handeln, so können wir "Wörterbuch 1" finden.

Während wir oft sagen: "foo ist ein Wörterbuch", das ist, weil wir faul sind - die Aussage ist technisch falsch. Richtig: "Es gibt ein Wörterbuch auf dem Heap und foo speichert seine Speicheradresse, so dass wir sie finden und benutzen können".

Wenn Sie führen Sie dann die Zeile:

foo = [bar mutableCopy]; 

Sie die Adresse in „bar“ werden mit einem anderen Objekt zu finden (ich nenne es „Dictionary 2“) in dem Haufen, und machen noch ein anderes Objekt ("Dictionary 3") auf dem Heap mit den gleichen Werten. Wenn Sie zählen, sind dies jetzt 3 Objekte.

Nachdem "Dictionary 3" erstellt wurde, wird seine Speicheradresse in der Variablen "foo" gespeichert. Diese Speicherung in "foo" überschreibt die vorhandene Speicheradresse (diejenige, die auf "Dictionary 1" zeigt). Dies bedeutet, dass wir keine verbleibenden Hinweise auf "Dictionary 1" haben und daher nie wieder finden können. Deshalb sagen wir "Wörterbuch 1" ist durchsickern.

Ich hoffe, Sie können aus dieser Situation sehen, warum "Dictionary 1" nie benötigt wurde (Sie wollten nur "foo" verwenden, um auf die Kopie zuzugreifen, "Dictionary 3").

3

Die erste ist korrekt, die zweite Speicher verliert, weil Sie zweimal zuweisen (Kopie zählt als eins) und nur einmal freigeben.

Vergessen Sie nicht, foo freizugeben, nachdem Sie fertig sind, obwohl

+0

Nicht freigeben. mutableCopy gibt ein automatisch freigegebenes Objekt zurück. – NilObject

+0

aus der Dokumentation: Der Aufrufer der Methode ist jedoch verantwortlich für die Freigabe des zurückgegebenen Objekts. – cobbal

+1

@NilObject: Nein, tut es nicht. Siehe http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-BEHDEDDB –

7

Sie nie den Code in dem zweiten Beispiel zu schreiben brauchen würde. Die [[NSMutableDictionary alloc] initWithCapacity:0] tut nichts außer Leckspeicher. Im zweiten Beispiel erstellen Sie ein NSMutableDictionary und weisen es foo zu. Dann weisen Sie in der nächsten Zeile eine Kopie eines anderen NSMutableDictionary an foo zu, was bedeutet, dass das ursprüngliche Verzeichnis foo, auf das verwiesen wird, jetzt irgendwo auf dem Heap abläuft und nicht mehr freigegeben werden kann.

Sie müssen jedoch in beiden Fällen foo freigeben, wie in der Objective-C memory management guidelines dargelegt.

+0

Geringfügige Korrektur: Die Zuweisung AFTER dieser Zeile führt zu einem Speicherverlust. Ich stimme Ihnen jedoch zu, dass dieser Code niemals geschrieben werden sollte. :-) –

1

Der Vorgang der Zuweisung überschreibt den vorherigen Wert, der von dieser Variablen gehalten wird. Zum Beispiel:

x = 3 
x = 4 

Der Wert von x zu Beginn der zweiten Zeile 3 gehalten, aber nach der Codezeile ausgeführt wird, ist es 4. Die Syntax:

int x = 0; 

ist wirklich nur Abkürzung dafür:

int x; 
x = 0; 

Variablen, die Zeiger sind nicht anders. Wenn also die erste Referenz der Variablen einfach zugewiesen werden soll, müssen Sie sie nicht zuerst initialisieren, denn der Wert, mit dem Sie sie initialisieren, wird einfach verworfen.

0

Die erste ist der richtige Weg, es zu tun. Sowohl kopieren als auch allokieren werden Ihrer Variablen Speicher zuweisen. Wenn Sie also die zweite Option verwenden, erhöht sich die Retain-Anzahl Ihrer Variablen auf 2.

Verwandte Themen