web-dev-qa-db-ja.com

Swift言語ではアンパサンド(&)はどういう意味ですか?

アンパーサンドはビット操作として知っていますが、変数名の前に表示されることがあります。変数の前に&を置くとどうなりますか?

41

inoutとして機能し、変数を入出力パラメーターにします。インアウトとは、実際には値ではなく参照によって値を渡すことを意味します。そして、参照によって値を受け入れるだけでなく、参照によって値を渡す必要があるため、単にfoo(&myVar)の代わりに&-foo(myVar)で渡します

ご覧のとおり、エラー参照を作成し、&を使用して関数に渡す必要がある場合、Swiftエラーが発生するか、変数を以前の状態に戻します

なぜ使用するのですか?関数が既に他の値を返し、別の値(エラーなど)を返すだけでは混乱する場合があるため、inoutとして渡します。他の場合は、関数が値を設定するために、多くの戻り値を反復処理する必要はありません。

それがあなたのお役に立てば幸いです!

56
Icaro

これは、in-out変数であることを意味します。その変数で直接何かをすることができます。コピーとしてではなく、アドレスで渡されます。

例えば:

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

&は関数内の変数の前にあります。つまり、この変数はinout変数です。

@Icaroはそれが何を意味するかをすでに説明しました。inout変数とin変数の違いを説明するための例を示します。

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

他の回答で述べたように、接頭辞&を使用して、 Functions> Function Argument Labelsで文書化されているように、メソッドまたは関数呼び出しのinoutパラメーターに値を渡します。パラメーター名> In-Outパラメーター inThe Swift Programming Language。しかし、それだけではありませんそれより。

実際には、Swift inoutパラメーターと、それらに値を渡すことを、CまたはC++のアドレスによる受け渡しまたは参照による受け渡しに似ていると考えることができます。実際、コンパイラーはinoutパラメーターの多くの使用をほぼ同じメカニズムにまで最適化します(特に、ポインターを処理するインポートされたCまたはObjC APIを呼び出す場合)。レベル、inoutは実際にはアドレスを渡しません。これにより、コンパイラーはこの言語をより柔軟で強力に構成できます。

たとえば、プロパティの1つへのアクセスを検証するための一般的な戦略を使用する構造体は次のとおりです。

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のゲッターとセッターは、最小/最大値を強制するなどのことを行うことができます。または、xは、ここでは、呼び出しをインスツルメントし、基礎となるプライベートプロパティを取得/設定します。

xinoutパラメーターに渡すとどうなりますか?

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関数を考えてみましょう。この関数は、任意の2つの「もの」を取り、それらの値を切り替えます。

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スタイルの「アドレスによる受け渡し」動作まで最適化する方法は、 で説明されています。宣言>関数> In-Outパラメーター inThe Swift Programming Language)。

4
rickster