Je suis curieux de savoir comment conserver / relâcher les travaux en interne. Sur le visage, il semble qu'il y ait un entier associé à chaque instance d'un Mais Jetez un coup d'oeil à Alors, où sont conserver les comptes pour des objets individuels stockés? Pas que je vais me battre avec elle, mais juste pour ma propre édification. P>
est-il stocké avec le NsObject code>, qui augmente et diminuée lorsque vous appelez
-Retain code> et
-Release code>, respectivement. p>
NsObject code>, la seule variable d'instance utilisée est la variable
ISA code>, pour déterminer son type de classe. P>
NsObject code>, mais caché dans certains détails de la mise en œuvre de l'objectif C? Si oui, cela semble être un mauvais design pour moi. Un devrait être en mesure de créer sa propre classe racine et de gérer leur propre compte de retenue / déverrouillage de la même manière (pas que c'est une bonne idée - il faudrait avoir un très em> bonne raison de ne pas utiliser
nsobject code>). p>
5 Réponses :
Cela ne sonne pas comme ça, mais juste au cas où ... si vous envisagez d'utiliser Conserver le nombre directement, ne . P>
En ce qui concerne les détails de la mise en œuvre, les sessions à la WWDC 2011 ont mentionné que, sous ARC, la majeure partie de la mise en œuvre du comptage de référence s'est déplacée dans l'OBJC Runtime. source pour cela est disponible , afin que vous puissiez découvrir vous-même Comment ça fonctionne. Pour le comptage de référence manuelle, une grande partie des comportements de l'OBJC sont reproduits dans la base de la fondation et de la libdispatch, qui sont également open source - si vous souhaitez mettre en œuvre un système similaire vous-même, ceux-ci pourraient s'avérer éducatif. P>
En général, il s'agit d'un détail de mise en œuvre pour la même raison que beaucoup de choses sont les suivantes: l'encapsulation est une bonne politique, en particulier pour les fournisseurs-cadres. Vous ne voulez pas les utilisateurs d'un cadre en fonction des détails de la mise en œuvre, car vous ne pouvez pas modifier votre implémentation sans casser leur code. P>
Nous ne savons pas exactement comment les données sont stockées, mais nous pouvons exclure quelques options:
Nous pouvons l'exclure, simplement parce que lorsque nous iTertons à travers les ivars de la classe et note que Même des propriétés de mise en œuvre privées existent dans la classe METDATA. P> Nous pouvons également l'exclure, car même les propriétés privées sont exposées dans les métadonnées de classes, comme indiqué par l'exemple suivant. , il n'y a pas de propriétés pour la classe Celui-ci est très difficile à exclure, Comme il n'y a pas de façons directes d'obtenir une liste de tous les objets associés. Cependant, étant donné que le concept d'objets associés est très nouveau et que le comptage de référence existe depuis toujours, je dis que cela n'est pas très probable. P> c'est mon meilleure estimation. Lorsque vous créez un NsObject, il s'agit d'une structure dans les coulisses. Que dire que la représentation de données NsObject réelle est quelque chose comme ceci: p> puis, lorsqu'un objet est créé: p> NsObject code>, nous ne voyons qu'un seul:
isa code>, comme indiqué dans ce programme: p>
propriétés privées h1>
NsObject code> Classe: p>
objets associés h1>
CoreFoundation structure-mangling h1>
id object_createInstance(...)
{
CFObjectRef object = malloc(sizeof(struct CFObject));
...
return (id) (object + sizeof(object->retainCount));
}
int object_retainCount(id self)
{
CFObjectRef asObject = (CFObjectRef) (self - sizeof(asObject->retainCount));
return asObject->retainCount;
}
Excellente réponse qui est également utile pour d'autres choses!
L'emplacement de stockage du comptage de retenue dépend à la fois du temps d'exécution utilisé et de la mise en œuvre de la classe. P>
Pour l'exécution de l'objectif-C Apple, vous pouvez comprendre beaucoup en creuser dans Le code source de l'exécution de l'objectif-C . p>
Par exemple, si vous utilisez ARC (et je pense même si vous n'êtes pas), le nombre de références pour la plupart des objets sont stockés dans des tables de hachage. Regardez la fonction Cependant, certaines classes remplacent _OBJC_ROOTETAIN CODE> dans
Runtime / objc-arr.mm code>. Je ne sais pas exactement pourquoi ils l'ont fait. Peut-être que c'est un moyen de conserver des comptes pour un meilleur comportement de cache (qui est important sous ARC, car l'ARC ajuste de retenir les comptes plus souvent que le code non arc ne le fait généralement pas). p>
conservent code> et des méthodes associées et stockent le nombre de retenons ailleurs. Par exemple, lors du débogage d'une fuite de mémoire, j'ai découvert que
Calayer code> le fait. Au lieu d'utiliser le mécanisme de comptage normal de retenue normal de l'exécution, un
Calayer code> stocke son compte de retenue dans un objet de mise en œuvre privé C ++. Ceci est plutôt frustrant car cela signifie que l'instrument d'allocations d'instruments ne se connecte pas conserve et des versions de
calayer code>. P>
Pour ajouter à cette question - une raison possible est que la classe NskonStantsTring doit avoir une mise en page très spécifique (voir ICI ) qui n'inclut pas un ivar de retenueCount. Alors que NSCONSTANTSTRING est une sous-classe de Nstring, qui est une sous-classe de NsObject, cela signifie que s'ils donnaient à NsObject un ivar supplémentaire, ils devraient construire la classe NskonStatifs à partir de zéro, essentiellement à partir d'une autre classe de base. Ceci est juste une raison, je suis sûr qu'il y a d'autres (meilleurs).
@Plpiper en fait, __ NSCFCONSTANTSTANTRING code> simplifie simplement
retenir code>,
libérant code> et
autorelease code> comme no-ops. Essayez
Disass -n '- [__ NSCFCONSTANTSTRING CONSERVEZ]' CODE> dans le débogueur. Il remplit également
retentaincount code> pour renvoyer
~ 0 code> (sur 32 bits) ou
~ 0UL >> 4 code> (sur 64 bits), et il A un jeu de bits d'indicateur qui indique
cfgetretaincount code> pour renvoyer une de ces valeurs.
Je ne sais pas si cela serait pertinent, mais j'ai trébuché sur le blog post sur la mise en œuvre des messages d'ordre supérieur dans l'objectif-c. L'auteur implémente l'objet HOM en tant que classe racine (c'est-à-dire non hérité de NsObject) et la mise en oeuvre ressemble à ceci: puis les méthodes de gestion du comptage de retenue sont implémentées comme ceci: p> - (id)retain {
__sync_add_and_fetch(&retainCount, 1);
return self;
}
- (id)autorelease {
[NSAutoreleasePool addObject:self];
return self;
}
- (void)release {
if (__sync_sub_and_fetch(&retainCount, 1) == 0) {
[methodSignatureForSelector release];
[forward release];
object_dispose(self);
}
}
Pour les aperçus d'addition, consultez http://www.mikeash.com/pyblog/friday-qa-2011-09-16- -2011-09-16-Lets-build-reference-counting.html , où Mike Ash explore une autre implémentation comme la seule Apple utilise . p>
WHENOUSERETAINECOUNT.COM
Lorsque nous parlons d'objets, elle devrait parfaitement parler de Boîtes noires , ce qui signifie que nous ne devrions pas nous soucier de Les détails des implémentations mais sur les interfaces. Vous proposez que Apple devait nous donner les détails de retenir le comptage, mais je dis avec la définition de l'interface que nous avons juste la bonne quantité de données que nous aurions besoin de la recréer. Nous avons kown, nous devons mettre en œuvre
-Retain code>,
-Release code>,
-DeAlloc code>, ... pour recréer la gestion de la mémoire NSOBJETCS - mais nous sommes libres de le faire Qui a-t-il de mieux pour nous.