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

app*_*ing 42 ampersand swift inout

我知道&符号有点操作,但有时候我会在变量名称前面看到它.是什么把一个&在前面的变量做?

Ica*_*aro 58

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

如你所见,你可以在Swift中使用它来处理错误,你必须创建一个错误引用,并使用&该函数将其传递给函数,如果发生错误则将填充错误值,或者将变量恢复为之前的状态

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

我希望能帮到你!

  • 它还可以用于从Swift调用C API,其中传统的C语义是"变量的地址".在Swift中,它采用UnsafePointer <Type>的形式.因此,例如在Swift中,期望指针的C API可能会采用UnsafePointer <CGFloat>的参数,您可以使用&myCGFloat调用它.(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html) (7认同)
  • @MoosaBaloch 在这种情况下,`&amp;` 是一个按位 AND 运算符 (2认同)

Leo*_*Leo 11

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

例如:

var temp = 10
func add(inout a: Int){
    a++
}
add(inout:&temp)
temp // 11
Run Code Online (Sandbox Code Playgroud)

  • ++ 已弃用 O:-) (2认同)

Wil*_*aan 9

如果&在函数中放入变量之前,则表示此变量是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
Run Code Online (Sandbox Code Playgroud)


Won*_*ray 8

Swift 语言中还有一个&符号的功能尚未提及。以下面的例子为例:

protocol Foo {}
protocol Bar {}

func myMethod(myVar: Foo & Bar) {
    // Do something
}
Run Code Online (Sandbox Code Playgroud)

这里的&符号语法声明同时myVar符合 Foo 和 Bar 协议。

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

func myMethod() -> UIViewController & UITableViewDataSource {
    // Do something
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这与问题无关,但这正是我正在寻找的,所以谢谢! (3认同)

ric*_*ter 5

正如其他答案中所述,您可以使用前缀&将值传递给inout方法或函数调用的参数,如《Swift 编程语言》中的Functions > Function Argument Labels and Parameter Names > In-OutParameters下所述。但事情还不止于此。

\n\n

在实践中,您可以将 Swiftinout参数和向它们传递值视为类似于 C 或 C++ 按地址传递或按引用传递。事实上,编译器会将参数的许多使用优化inout为大致相同的机制(特别是当您调用处理指针的导入 C 或 ObjC API 时)。然而,这些只是语义层面上的优化 \xe2\x80\x94,inout实际上并没有传递地址,这可以释放编译器,使这种语言构造更加灵活和强大。

\n\n

例如,这里的结构使用通用策略来验证对其属性之一的访问:

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

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

\n\n

x现在,当我们传递一个参数时会发生什么inout

\n\n
func plusOne(num: inout Int) {\n    num += 1\n}\n\nvar pt = Point(x: 0, y: 1)\nplusOne(num: &pt.x)\n// prints:\n//   get x: 0\n//   set x: 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,即使x是计算属性,使用参数“通过引用”传递它的效果与您期望的(如果是存储属性或局部变量)inout相同。x

\n\n
\n\n

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

\n\n
var a = 1, b = 2\nswap(&a, &b)\nprint(a, b) // -> 2 1\n\nvar dict = [ "Malcolm": "Captain", "Kaylee": "Mechanic" ]\nswap(&dict["Malcolm"], &dict["Kaylee"])\nprint(dict) // -> ["Kaylee": "Captain", "Malcolm": "Mechanic"], fanfic ahoy\n\nlet window1 = NSWindow()\nlet window2 = NSWindow()\nwindow1.title = "window 1"\nwindow2.title = "window 2"\nvar windows = [window1, window2]\nswap(&windows[0], &windows[1])\nprint(windows.map { $0.title }) // -> ["window 2", "window 1"]\n
Run Code Online (Sandbox Code Playgroud)\n\n

这种inout工作方式还可以让您做一些有趣的事情,例如+=在嵌套调用链上使用运算符:

\n\n
window.frame.origin.x += 10\n
Run Code Online (Sandbox Code Playgroud)\n\n

CGRect...这比仅仅分解一个具有不同坐标的新的要简单得多x

\n\n
\n\n

这种更细致的行为版本inout,称为“按值结果调用”,以及它可以优化为 C 风格的“按地址传递”行为的方法,在《Swift 编程语言》中的声明 > 函数 > 输入输出参数中进行了介绍。 。

\n