41 votes

NSError et __autoreleasing

Quelqu'un peut-il m'expliquer l'utilité d'avoir des __autoreleasing dans l'exemple de code suivant ?

- (void)execute:(NSError * __autoreleasing *)error {
    // do stuff, possibly assigning error if something went wrong
}

J'ai enlevé le __autoreleasing et tout semble encore compiler/exécuter correctement. J'ai commencé à utiliser obj-c après ARC, donc je n'ai jamais vraiment appris/compris tous ces trucs de double soulignement. J'ai lu le Guide de transition ARC mais je ne comprends pas bien leur exemple de NSError.

85voto

CRD Points 21578

Examinez la façon dont l'ARC travaille avec variables - chaque variable de référence a un mode (implicite ou explicite) : fort , faible , etc. Ce mode permet à ARC de savoir comment gérer les lectures et les écritures dans cette variable. fort La lecture d'une variable ne nécessite aucune action supplémentaire, tandis que l'écriture nécessite la libération de la référence existante dans la variable avant qu'elle ne soit remplacée par la nouvelle. L'ARC doit connaître le mode de toute variable pour fonctionner.

Considérons maintenant les variables qui sont elles-mêmes passées par référence , par exemple pour votre execute vous recevrez un appel du genre :

NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value

et le corps de execute contiendra une affectation du type

- (void)execute:(NSError * __autoreleasing *)error
{
   ...
   if (error != NULL)
      *error = [NSError ...]; // assign indirectly via the reference to a variable
   ...
}

Pour l'affectation indirecte, l'ARC doit connaître le mode de la variable référencée afin de savoir comment lire et écrire. C'est ce que la fonction __autoreleasing se trouve dans la déclaration, il indique à ARC qu'on lui a passé une référence à une variable dont le mode est location automatique (autoreleasing) et cela indique à ARC comment lire et écrire le contenu de la variable. Supprimez l'élément __autoreleasing et un mode par défaut sera pris en compte, et dans ce cas, je pense qu'il est préférable d'être explicite.

En location automatique (autoreleasing) signifie que la variable contient une référence qui n'est pas possédée, les lectures devraient retenir si nécessaire et écrit peut simplement écrire. Il est utilisé principalement pour les variables passées par référence.

Vous remarquerez peut-être que dans l'exemple ci-dessus, la variable myError a mode fort (implicitement) et pourtant il est passé par référence en tant que location automatique (autoreleasing) - le compilateur gère cela automatiquement en introduisant une variable temporaire autoreleasing, en copiant la variable sin en conservant la référence actuelle dans myError et de passer le temporaire par référence en tant qu'argument de la commande execute: . Après le retour de l'appel, le compilateur effectue une affectation normale de l'élément temporaire à l'élément myError ce qui a pour effet de libérer l'ancienne référence et de conserver celle qui a été renvoyée.

Pour plus de détails, voir Apple passe aux notes de version ARC

Suivi des commentaires

Q : Est-ce que __autoreleasing implicitement défini ?

A : Eh bien Apple's n'est pas spécifique, mais le document Documentation Clang indique qu'il est implicite pour les paramètres indirects. Comme ci-dessus, je recommanderais d'être explicite, la clarté est une bonne chose™.

Q : Le placement a-t-il de l'importance ?

R : Oui, et non... Il s'agit d'une déclaration en C, qui fait l'objet de questions de quiz ("Que déclare ce qui suit..."). Le qualificatif devrait se trouver entre les deux astérisques, puisqu'il s'agit d'un pointeur sur une (variable de type) pointeur à libération automatique sur un objet Mais Apple déclare que le compilateur est "tolérant" sans préciser ce qu'il tolère. Jouez la sécurité, mettez-le au bon endroit.

Q : Ne devriez-vous pas tester les error être NULL avant de procéder à l'affectation indirecte ?

R : Bien sûr que si, quelque part avant de faire l'indirection. Le code présenté n'est qu'une esquisse et ce genre de détail a été éludé et couvert par la rubrique ... 's. Toutefois, comme la question a été soulevée à plusieurs reprises au fil des ans, il se peut que j'aie trop éludé la question. if a été ajouté.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X