&符号(&)在Swift语言中的含义是什么?

时间:2015-05-30 01:22:38

标签: swift ampersand inout

我知道&符号有点操作但有时候我会在变量名前面看到它。将&放在变量前面会有什么作用?

5 个答案:

答案 0 :(得分:55)

它用作inout以使变量成为输入输出参数。 In-out实际上意味着通过引用而不是通过值传递值。它不仅要求通过引用接受值,还要通过引用传递它,所以将它传递给& - foo(&myVar)而非foo(myVar)

如您所见,您可以在Swift的错误处理中使用它,您必须创建错误引用并使用&将其传递给函数,如果发生错误或传递变量,函数将填充错误值回到原来之前

为什么要使用它?有时函数已经返回其他值,只返回另一个(如错误)会让人感到困惑,所以我们将它作为inout传递。其他时候我们希望函数填充值,因此我们不必迭代大量的返回值,因为函数已经为我们做了 - 以及其他可能的用途。

我希望能帮到你!

答案 1 :(得分:9)

这意味着它是一个输入输出变量。您可以直接使用该变量执行某些操作。它是通过地址传递的,而不是副本。

例如:

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

答案 2 :(得分:8)

如果将&放在函数中的变量之前,则表示此变量是 inout 变量。

@Icaro已经描述了它的含义,我将举一个例子来说明inout变量和变量之间的区别:

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

答案 3 :(得分:4)

如其他答案中所述,您使用前缀&将值传递给方法或函数调用的inout参数,如 The Swift中的Functions > Function Argument Labels and Parameter Names > In-Out Parameters所述编程语言。但是还有更多的东西。

在实践中,您可以考虑Swift inout参数并将值传递给它们,因为它们类似于C或C ++传递地址或传递引用。实际上,编译器会将inout参数的许多用法优化为大致相同的机制(特别是当您调用导入指针的导入C或ObjC API时)。然而,这些只是优化 - 在语义层面上,inout实际上不会传递地址,从而使编译器可以使这种语言构造更加灵活和强大。

例如,这是一个结构,它使用一个通用策略来验证对其中一个属性的访问:

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 }
}

(在“真实”代码中,x的getter和setter可以执行诸如强制最小值/最大值之类的操作。或者x可以执行其他计算属性技巧,例如与SQL数据库交谈在这里我们只是检测调用并获取/设置底层私有财产。)

现在,当我们将x传递给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

因此,即使x是计算属性,使用inout参数“通过引用”传递它的工作方式也与预期存储x时相同。属性或局部变量。

这意味着你可以通过C / C ++ / ObjC中甚至无法考虑的“引用”传递各种各样的东西。例如,考虑标准库swap函数,它接受任何两个......“事物”并切换它们的值:

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"]

inout的工作方式也可以让您在嵌套的调用链中使用+=运算符等有趣的东西:

window.frame.origin.x += 10

...这比分解CGRect只是为了构建一个具有不同x坐标的新的更简单。

inout行为的这个更细微的版本,称为“按值调用结果”,以及它可以优化为C风格的“按地址传递”行为的方式,涵盖在Declarations > Functions > In-Out Parameters下在 Swift编程语言中。

答案 4 :(得分:2)

Swift语言中的&符号还有另一个功能尚未提及。请看以下示例:

protocol Foo {}
protocol Bar {}

func myMethod(myVar: Foo & Bar) {
    // Do something
}

此处的&符号表示myVar同时符合Foo和Bar协议。

作为另一个用例,请考虑以下事项:

func myMethod() -> UIViewController & UITableViewDataSource {
    // Do something
}

这里我们说的是该方法返回的类实例(UIViewController的)符合某种协议(UITableViewDataSource)。 Swift 5.1的Opaque Types使它有些过时,但是您可能会不时在Swift 5.1之前的代码中看到这种语法。