Swift の文字列は、参照型ではなく値型です。つまり、アイデンティティではなく、価値があるだけです。この意味で、2 つの文字列が同じ「同一性」を持っているかどうかをチェックしても意味がありません。それらが同じ変数でない限り、それらは異なります。代わりに、を使用して同じ値を持っているかどうかを確認する必要があります==
。
ボンネットの下には、インターンがいる場合があります。実際、間違いなく次のようなものがあります。
struct StringBits {
let underlyingPtr: UnsafeMutablePointer<Void>
let padding1: UnsafeMutablePointer<Void>
let padding2: UnsafeMutablePointer<Void>
}
let s1 = "abcd"
let s2 = "abcd"
let bits1 = unsafeBitCast(s1, StringBits.self)
let bits2 = unsafeBitCast(s2, StringBits.self)
println(bits1.underlyingPtr) // 0x0000000117654000
println(bits2.underlyingPtr) // also 0x0000000117654000
同様に、ある文字列を別の文字列から初期化すると、それらのいずれかが変更されるまで同じストレージが共有されます (つまり、文字列はコピー オン ライトになります)。
しかし、これらの詳細は、知る必要のない実装の詳細として隠されています。セマンティクスに関する限り、s1
まったくs2
無関係です。
パフォーマンスが気になる場合、基になる String 型はおそらくそのストレージへのポインターを使用して、同じストレージを共有している場合に同等性を効率的にチェックします。ここに見られるように、配列 (同様に実装されています) も同様です。
struct NeverEqual: Equatable { }
// NOT a correct implementation of ==, since == must be
// reflexive, and this isn’t:
func ==(lhs: NeverEqual, rhs: NeverEqual)->Bool { return false }
let x=[NeverEqual()]
let y=x
// this returns true – because it doesn’t bother comparing the
// elements, because it knows x and y share the same storage
x==y