10
protocol A {
    func f()
}

struct S1 : A {
    func f() {
        print("S1")
    }
}

struct S2 : A {
    func f() {
        print("S2")
    }
}

let array: [A] = [S1(), S2()]

for s: A in array {
    s.f()
}

// "S1\n" "S2\n"

これが継承階層である場合、Swift は v-table を使用して正しい実装を検索することを期待します。しかし、具体的な型はarrayを実装するものであれば何でもA構いませんし、その他のプロトコルもいくらでもあります。Swift ランタイムは、v-tables も使用している場合、オブジェクトの構造をどのように知るのでしょうか?

4

1 に答える 1

14

Swift ランタイムは、プロトコル メソッドの各型の実装へのポインターを保持する Protocol Witness Table を使用します。

Mike Ash は、彼の記事Exploring Swift Memory Layout, Part IIで最もよく説明しています。

オフセット 32 にある最後のものは、基になる型とプロトコルの「プロトコル監視テーブル」であり、プロトコル メソッドの型の実装へのポインターが含まれています。これは、実行時に基になる型を知らなくても、コンパイラがプロトコル型の値に対して p() などのメソッドを呼び出すことができる方法です。

ハミッシュのコメントで提案されているように、WWDC ビデオUnderstanding Swift Performanceも見ます。

于 2016-07-12T15:32:27.673 に答える