2009-03-20 5 views
6

C'est une question de niveau débutant dans lequel je suis curieux de savoir si cela est une utilisation valide d'un pointeur dans un énoncé tel que:Est-ce une utilisation valide d'un pointeur Objective-C?

NSMutableDictionary *foo = [bar mutableCopy]; 

Je deviens confus quand cela est valable contre quand je dois procédez comme suit:

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

Les deux sont-ils valides? Quand utiliser l'un sur l'autre?

Répondre

9

Deviner pourquoi vous pourriez être confus, je voudrais ajouter une explication de ce que le deuxième exemple de code fait réellement (et pourquoi ce n'est pas nécessaire). Je pense que vous êtes confus par cette ligne parce que cette ligne est souvent décrite comme "initialisant foo". C'est un peu trompeur. Techniquement, 2 entités différentes sont modifiées ici - le nouvel objet NSMutableDictionary est créé et la variable "foo" reçoit son adresse.

La ligne crée en réalité un nouvel objet NSMutableDictionary sur le tas (zone de mémoire dynamique de votre application). Je l'appellerai "Dictionnaire 1". Pour que ce nouvel objet "Dictionary 1" sur le tas puisse être trouvé, son adresse mémoire est stockée dans "foo". Le rôle de "foo" est d'agir comme un index, donc nous pouvons trouver "Dictionary 1".

Alors que nous disons souvent: "foo est un dictionnaire", c'est parce que nous sommes paresseux - la déclaration est techniquement fausse. Correctement: "il y a un dictionnaire sur le tas et foo stocke son adresse mémoire afin que nous puissions le trouver et l'utiliser".

Lorsque vous exécutez ensuite la ligne:

foo = [bar mutableCopy]; 

vous utilisez l'adresse dans « bar » pour trouver un autre objet (je vais l'appeler « Dictionnaire 2 ») dans le tas, et faire encore un autre objet ("Dictionnaire 3") sur le tas avec les mêmes valeurs. Si vous tenez compte, c'est maintenant 3 objets en existence. Après que "Dictionary 3" est créé, son adresse mémoire est ensuite stockée dans la variable "foo". Ce stockage dans "foo" écrase l'adresse mémoire existante (celle qui pointait vers "Dictionary 1"). Cela signifie que nous n'avons plus de pointeurs sur "Dictionary 1" et que nous ne pourrons jamais le retrouver. C'est pourquoi nous disons que "Dictionary 1" a fui.

J'espère que vous pouvez voir à partir de cette situation pourquoi "Dictionary 1" n'a jamais été nécessaire (vous avez seulement l'intention d'utiliser "foo" pour accéder à la copie, "Dictionary 3").

3

Le premier est correct, le second fuit la mémoire car vous allouez deux fois (la copie compte pour un) et ne relâchez qu'une seule fois.

Ne pas oublier de libérer foo après que vous avez terminé si

+0

Ne le relâchez pas. mutableCopy renvoie un objet autoreleased. – NilObject

+0

à partir de la documentation: L'invocateur de la méthode est toutefois responsable de la libération de l'objet renvoyé. – cobbal

+1

@NilObject: Non, ce n'est pas le cas. Voir http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-BEHDEDDB –

7

Vous ne devez écrire le code dans le second exemple. Le [[NSMutableDictionary alloc] initWithCapacity:0] ne fait rien, sauf la mémoire de fuite.

Dans le deuxième exemple, vous créez un NSMutableDictionary et l'affectez à foo. Ensuite, dans la ligne suivante, vous affectez une copie d'un autre NSMutableDictionary à foo, ce qui signifie que le dictionnaire original foo pointé vers est maintenant juste en train de flotter quelque part sur le tas, incapable d'être jamais libéré.

Dans les deux cas, vous devrez libérer foo, comme indiqué dans le Objective-C memory management guidelines.

+0

Correction mineure: l'affectation APRÈS cette ligne est ce qui fuit la mémoire. Cependant, je suis d'accord avec vous que ce code ne devrait jamais être écrit. :-) –

1

L'action d'affectation écrase la valeur précédente détenue par cette variable. Par exemple:

x = 3 
x = 4 

La valeur détenue par x au début de la deuxième ligne est 3, mais après la ligne de l'exécution du code, il est 4. La syntaxe:

int x = 0; 

est vraiment juste raccourci pour cela:

int x; 
x = 0; 

Les variables qui sont des pointeurs ne sont pas différentes. Ainsi, si la première référence de la variable est simplement de l'assigner, vous n'avez pas besoin de l'initialiser, car toute valeur avec laquelle vous l'initialisez sera simplement supprimée.

0

Le premier est la bonne façon de le faire. Copy et alloc alloueront de la mémoire à votre variable. Donc, en utilisant la deuxième option augmentera le nombre de retenue de votre variable à 2.

Questions connexes