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é.