3
3

More than 5 years have passed since last update.

Assignment and Copy Behavior for Arrays

Last updated at Posted at 2014-06-08

SwiftではDictionary型とArray型で参照渡しなのか値渡しなのか混乱しやすそうな部分がある。

Dictionary

Swiftの場合、多くの言語と同じようにClassやObjectが参照渡しでStructやInt,Stringなどは値がコピーされる。DictionaryはStructとして内部では実装されているらしいので値渡しとなる。例えば以下のコード

var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19]
var copiedAges = ages

Dictionaryを他の変数に代入している。ここでDictionaryは値渡しでコピーされるのでcopiedAgesagesは別物。

copiedAges["Peter"] = 24
println(ages["Peter"])
// prints "23"

実際copiedAgesに変更を加えてもagesには影響がない。

Array

Arrayの場合は話がもう少し複雑。ArrayもDictionaryと同じようにStructで実装されているので基本的には値渡しかと思いきや、こちらは参照が渡されてしまう。

var a = [1, 2, 3]
var b = a
var c = a

a[0] = 42
println(a[0])
// 42
println(b[0])
// 42
println(c[0])
// 42

何故かbcまで変わっている。なるほどArrayの場合は参照渡しになっているのねと思いきや、そうならない場合もある。実はArrayの長さを変更するような操作を行う場合には新しいArrayが作られてしまう。

a.append(4) // <- ここで長さが変わる
a[0] = 777
println(a[0])  // <- そうするとaには新しいArrayが入るみたい
// 777
println(b[0])
// 42
println(c[0])
// 42

というわけでaの参照する先とb,cが参照する先は異なるようになるので値が変更されないことになる。
基本的にはArrayは参照渡しになってしまう。

参照を渡したくない

勝手に他の変数を通じてArrayが書き換えられるのはあまり気分のいいものではない。そこでArrayの代入を行っても別の参照を持ってくれるようにする方法がある。

b.unshare()
b[0] = 100
println(b[0])
// 100
println(c[0])
// 42

unshareを呼ぶと、bにはcと異なるArrayを持ってくれることになる。

でも個人的にはcopyを使う方がわかりやすい。

var b = a.copy()

とやっておくとbにはaのコピーが入る。

参照:The Swift Programming Language -Classes and Strucures-

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3