web-dev-qa-db-fra.com

Que signifie une esperluette (&) dans la langue Swift?

Je connais l'esperluette comme une opération un peu mais parfois je la vois devant des noms de variables. Que signifie mettre un & devant les variables faire?

41

Il fonctionne comme un inout pour faire de la variable un paramètre d'entrée-sortie. In-out signifie en fait passer la valeur par référence, pas par valeur. Et cela nécessite non seulement d'accepter la valeur par référence, mais aussi de la transmettre par référence, alors passez-la avec & - foo(&myVar) au lieu de simplement foo(myVar)

Comme vous le voyez, vous pouvez l'utiliser dans la remise d'erreur Swift où vous devez créer une référence d'erreur et la transmettre à la fonction en utilisant & la fonction remplira la valeur d'erreur si une erreur se produit ou transmettra la variable comme avant

Pourquoi l'utilisons-nous? Parfois, une fonction renvoie déjà d'autres valeurs et le simple fait d'en renvoyer une autre (comme une erreur) serait déroutant, nous la transmettons donc comme une entrée. D'autres fois, nous voulons que les valeurs soient remplies par la fonction afin que nous n'ayons pas à répéter sur de nombreuses valeurs de retour, car la fonction l'a déjà fait pour nous - entre autres utilisations possibles.

J'espère que cela vous aide!

56
Icaro

Cela signifie qu'il s'agit d'une variable d'entrée-sortie. Vous pouvez faire quelque chose directement avec cette variable. Il est transmis par adresse et non comme copie.

Par exemple:

var temp = 10
func add(inout a: Int){
    a++
}
add(&temp)
temp // 11
10
Leo

Si vous mettez & devant une variable dans une fonction, cela signifie que cette variable est inout variable.

@Icaro a déjà décrit ce que cela signifie, je vais juste donner un exemple pour illustrer la différence entre les variables inout et les variables:

func majec(inout xValue:Int, var yValue:Int) {
    xValue = 100
    yValue = 200
}

var xValue = 33
var yValue = 33
majec(&xValue, yValue: yValue)
xValue //100
yValue //33
9
William Kinaan

Comme indiqué dans d'autres réponses, vous utilisez le préfixe & pour passer une valeur à un paramètre inout d'un appel de méthode ou de fonction, comme indiqué sous Fonctions> Étiquettes des arguments de fonction et noms des paramètres> Paramètres d'entrée-sortie in Le Swift langage de programmation . Mais il y a plus que cela.

En pratique, vous pouvez penser aux paramètres Swift inout et leur transmettre des valeurs comme étant similaires à C-C++ pass-by-address ou pass-by-reference. En fait, le compilateur optimisera de nombreuses utilisations des paramètres inout à peu près les mêmes mécanismes (en particulier lorsque vous appelez des API C ou ObjC importées qui traitent des pointeurs). Cependant, ce ne sont que des optimisations - au niveau sémantique niveau, inout ne transmet vraiment pas d'adresses, ce qui libère le compilateur pour rendre cette construction de langage plus flexible et plus puissante.

Par exemple, voici une structure qui utilise une stratégie commune pour valider l'accès à l'une de ses propriétés:

struct Point {
    private var _x: Int
    var x: Int {
        get {
            print("get x: \(_x)")
            return _x
        }
        set {
            print("set x: \(newValue)")
            _x = newValue
        }
    }
    // ... same for y ...
    init(x: Int, y: Int) { self._x = x; self._y = y }
}

(Dans le "vrai" code, le getter et le setter pour x pourraient faire des choses comme appliquer des valeurs minimum/maximum. Ou x pourrait faire d'autres astuces de propriétés calculées, comme parler à une base de données SQL sous Ici, nous instrumentons simplement l'appel et obtenons/définissons la propriété privée sous-jacente.)

Maintenant, que se passe-t-il lorsque nous passons x à un paramètre inout?

func plusOne(num: inout Int) {
    num += 1
}

var pt = Point(x: 0, y: 1)
plusOne(num: &pt.x)
// prints:
//   get x: 0
//   set x: 1

Ainsi, même si x est une propriété calculée, la transmettre "par référence" à l'aide d'un paramètre inout fonctionne de la même manière que vous vous y attendez si x était un stocké ou une variable locale.


Cela signifie que vous pouvez passer toutes sortes de choses "par référence" que vous ne pouviez même pas considérer en C/C++/ObjC. Par exemple, considérons la fonction standard de bibliothèque swap, qui prend deux ... "choses" et change leurs valeurs:

var a = 1, b = 2
swap(&a, &b)
print(a, b) // -> 2 1

var dict = [ "Malcolm": "Captain", "Kaylee": "Mechanic" ]
swap(&dict["Malcolm"], &dict["Kaylee"])
print(dict) // -> ["Kaylee": "Captain", "Malcolm": "Mechanic"], fanfic ahoy

let window1 = NSWindow()
let window2 = NSWindow()
window1.title = "window 1"
window2.title = "window 2"
var windows = [window1, window2]
swap(&windows[0], &windows[1])
print(windows.map { $0.title }) // -> ["window 2", "window 1"]

La façon dont inout fonctionne vous permet également de faire des trucs amusants comme utiliser le += opérateur sur les chaînes d'appel imbriquées:

window.frame.Origin.x += 10

... ce qui est beaucoup plus simple que de décomposer un CGRect juste pour en construire un nouveau avec une coordonnée x différente.


Cette version plus nuancée du comportement inout, appelée "résultat d'appel par valeur", et les façons dont elle peut optimiser le comportement de "passage par adresse" de style C, sont couvertes sous Déclarations> Fonctions > Paramètres In-Out in Le Swift .

4
rickster