Je suis vraiment nouveau sur Swift et je viens de lire que les classes sont passées par référence et que les tableaux / chaînes, etc. sont copiés.
Le passage par référence est-il de la même manière qu'en Objective-C ou Java où vous passez réellement "une" référence ou est-ce un passage par référence approprié?
swift
pass-by-reference
pass-by-value
pass-by-pointer
gran_profaci
la source
la source
Réponses:
Types de choses à Swift
La règle est:
Les instances de classe sont des types de référence (c'est-à - dire que votre référence à une instance de classe est en fait un pointeur )
Les fonctions sont des types de référence
Tout le reste est un type valeur ; "tout le reste" signifie simplement des instances de structs et des instances d'énumérations, car c'est tout ce qu'il y a dans Swift. Les tableaux et les chaînes sont des instances de struct, par exemple. Vous pouvez passer une référence à l'une de ces choses (en tant qu'argument de fonction) en utilisant
inout
et en prenant l'adresse, comme newacct l'a souligné. Mais le type est lui-même un type valeur.Ce que les types de référence signifient pour vous
Un objet de type référence est spécial dans la pratique car:
La simple affectation ou le passage à une fonction peut produire plusieurs références au même objet
L'objet lui-même est modifiable même si sa référence est une constante (
let
explicite ou implicite).Une mutation de l'objet affecte cet objet tel que vu par toutes les références à celui-ci.
Ceux-ci peuvent être des dangers, alors gardez un œil sur. D'un autre côté, passer un type de référence est clairement efficace car seul un pointeur est copié et passé, ce qui est trivial.
Ce que les types de valeur signifient pour vous
Clairement, passer un type valeur est "plus sûr" et
let
signifie ce qu'il dit: vous ne pouvez pas muter une instance de struct ou une instance enum via unelet
référence. D'un autre côté, cette sécurité est obtenue en faisant une copie séparée de la valeur, n'est-ce pas? Cela ne rend-il pas le passage d'un type valeur potentiellement coûteux?Eh bien, oui et non. Ce n'est pas aussi grave que vous pourriez le penser. Comme Nate Cook l'a dit, passer un type valeur n'implique pas nécessairement une copie, car
let
(explicite ou implicite) garantit l'immuabilité, il n'est donc pas nécessaire de copier quoi que ce soit. Et même passer dans unevar
référence ne signifie pas que les choses seront copiées, seulement qu'elles peuvent l' être si nécessaire (car il y a une mutation). Les docs vous conseillent spécifiquement de ne pas mettre votre culotte dans une torsion.la source
inout
quel que soit son type. Le fait que quelque chose soit pass-by-reference est orthogonal aux types.Il est toujours pass-by-value lorsque le paramètre ne l'est pas
inout
.Il est toujours pass-by-reference si le paramètre est
inout
. Cependant, cela est quelque peu compliqué par le fait que vous devez utiliser explicitement l'&
opérateur sur l'argument lors du passage à uninout
paramètre, il peut donc ne pas correspondre à la définition traditionnelle du passage par référence, où vous passez la variable directement.la source
inout
)inout
n'est en fait pas un passage par référence mais une copie par copie. Cela garantit seulement qu'après l'appel de la fonction, la valeur modifiée sera affectée à l'argument d'origine. Paramètres d'Tout dans Swift est passé par "copie" par défaut, donc lorsque vous passez un type valeur, vous obtenez une copie de la valeur, et lorsque vous passez un type référence, vous obtenez une copie de la référence, avec tout ce que cela implique. (Autrement dit, la copie de la référence pointe toujours vers la même instance que la référence d'origine.)
J'utilise des citations effrayantes autour de la "copie" ci-dessus parce que Swift fait beaucoup d'optimisation; dans la mesure du possible, il ne se copie pas tant qu'il n'y a pas de mutation ou de possibilité de mutation. Étant donné que les paramètres sont immuables par défaut, cela signifie que la plupart du temps, aucune copie ne se produit.
la source
Voici un petit exemple de code pour passer par référence. Évitez de faire cela, sauf si vous avez une bonne raison de le faire.
Appelez ça comme ça
la source
inout
est un opérateur de copie d'entrée et de sortie. Il copiera d'abord l'objet, puis écrasera l'objet d'origine après le retour de la fonction. Bien que cela puisse sembler identique, il existe des différences subtiles.Le blog Apple Swift Developer contient un article intitulé Value and Reference Types qui fournit une discussion claire et détaillée sur ce sujet.
Citer:
Le billet de blog Swift continue d'expliquer les différences avec des exemples et suggère quand vous utiliseriez l'un plutôt que l'autre.
la source
Les classes sont passées par références et les autres sont passées par valeur par défaut. Vous pouvez passer par référence en utilisant le
inout
mot - clé.la source
inout
est un opérateur de copie d'entrée et de sortie. Il copiera d'abord l'objet, puis écrasera l'objet d'origine après le retour de la fonction. Bien que cela puisse sembler identique, il existe des différences subtiles.Lorsque vous utilisez inout avec un opérateur infixe tel que + =, le symbole & adresse peut être ignoré. Je suppose que le compilateur suppose un passage par référence?
origDictionary + = nouveauDictionaryToAdd
Et joliment ce dictionnaire 'ajouter' n'écrit qu'une seule fois dans la référence d'origine, donc idéal pour le verrouillage!
la source
Classes et structures
L'une des différences les plus importantes entre les structures et les classes est que les structures sont toujours copiées lorsqu'elles sont transmises dans votre code, mais les classes sont passées par référence.
Fermetures
Si vous affectez une fermeture à une propriété d'une instance de classe et que la fermeture capture cette instance en faisant référence à l'instance ou à ses membres, vous créerez un cycle de référence fort entre la fermeture et l'instance. Swift utilise des listes de capture pour briser ces cycles de référence solides
ARC (comptage automatique de références)
Le comptage de références s'applique uniquement aux instances de classes. Les structures et les énumérations sont des types valeur, pas des types référence, et ne sont ni stockées ni transmises par référence.
la source