Swiftの値渡しと参照渡しに関するまとめ
19/03/10 13:51:28 19/06/02 13:50:52
Swiftの値渡しと参照渡しの概要や方法について解説します。
Swiftをベースに解説しますが、値渡し、参照渡し自体はSwift以外のプログラミング言語にも存在する概念です。Swiftで勉強しておけば他の言語にも応用が利くので、一石二鳥です。
値渡しと参照渡しとは
値渡しと参照渡しの違いについて解説します。まず値渡しとは、関数に変数を渡す際に変数をコピーして渡す方法です。次に、参照渡しは関数に変数を渡す際に、変数が置かれた場所を渡す方法です。
いずれにしても値そのものを直接渡すわけでなく、コピーか場所を書いてあるメモを渡すイメージです。これだけの違いなのですが、処理の結果大きく異なる点があり、注意しなければならない点でもあります。
まず、値渡しは値をコピーして渡すので書き換えても元のデータに何の影響も与えません。操作した結果影響が与えられるのはあくまでもコピーした方の値になります。一方で、参照渡しはデータを書き換えると直接内容が書き換わります。
用語の印象的には値渡しが値の書き換えが行われ、参照渡しなら値を書き換えても直接書き換えられないような感じがします。実際そういった勘違いがされることもあります。ここが注意点で、値渡しは直接値を書き換えず、参照渡しは直接値を書き換えるという点を確実に押さえておく必要があります。
情報処理試験にも出てきている
値渡しと参照渡しは情報処理試験の頻出問題で、たとえば基本情報技術者試験を勉強した経験のある方はそれを思い出すと良いでしょう。四角いブロックが積み重なっており、その中と外に値と番地が書かれた図を見た記憶のある方は多いかと思います。
あれがまさに値渡しと参照渡しを理解するのにぴったりの図です。ブロック一つ一つはメモリを表していますが、ブロックのなかのものをコピーして渡すのが参照渡しです。要するに、メモリに入っているデータをそっくりそのまま別のメモリ領域にコピーします。
参照渡しはメモリの番地を渡す方法です。番地を渡せばその番地を使って元の値が格納されているメモリ領域にアクセスできます。情報処理試験の勉強をしたことのある方は、そのときの図をイメージしながらプログラミングするとより理解しやすくなり、自分の書いているコードの意味がわかりやすくなるはずです。
値渡しのサンプルコード
Swiftの値渡しのサンプルコードは以下です。
@IBAction func byPerformSegue(_ sender: Any) {
self.performSegue(withIdentifier: "toSegueViewController", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toSegueViewController" {
let nextVC = segue.destination as! SegueViewController
nextVC.text = "fromViewController"
}
}
値渡しで画面遷移するためのコードです。iOSの実践的なコードなので少し何を書いているのかわかりにくいですが、segueを使用して画面遷移と値渡しを行っています。また同様に navigationControllerを使用して画面遷移と値渡しを行う方法です。
@IBAction func byNavicationPush(_ sender: Any) {
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "navigationPushView") as! NavigationPushViewController
nextVC.text = "fromViewController"
self.navigationController?.pushViewController(nextVC, animated: true)
}
presentを使用して画面遷移と値渡しを行うことも可能です。
@IBAction func byPresent(_ sender: Any) {
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "presentView") as! PresentViewController
nextVC.text = "fromViewController"
self.present(nextVC, animated: true, completion: nil)
}
}
参照渡しのサンプルコード
値渡しはやや実践的なコードで紹介しました。参照渡しについても実践的なコードで紹介しても良いのですが、わかりやすいように簡易的なコードで紹介します。サンプルコードは以下です。
func doubleNum (inout i1: Int, inout i2: Int) {
i1 = i1 * 2
i2 = i2 * 2
}
var x = 2
var y = 3
print(x) // 2
print(y) // 3
doubleNum(&x, i2: &y)
print(x) // 4
print(y) // 6
値渡しと違って参照場所を渡しているため値を操作すると直接書き換えられます。inout を付けて引数を宣言すると、引数に値のコピーが渡り、関数を実行した結果の値がコピーされて呼び出し元に書き戻されます。
構造体とクラス
Swiftの構造体は値渡しのみの仕様となっており、参照渡しではありません。クラスはクラスオブジェクトを作って元のクラスを参照しますが、この点で構造体とクラスには大きな違いがあります。
Swiftで値渡しと参照渡しを理解するためには、構造体とクラスの違いを知っておいた方が良いです。違いを知るためのサンプルコードは以下です。
// 構造体
struct UserStruct {
var age: Int
init (age: Int){
self.age = age
}
}
// クラス
class UserClass {
var age: Int
init (age: Int){
self.age = age
}
}
var userStruct1 = UserStruct(age: 30)
var userStruct2 = userStruct1
// 新しい構造体として代入されるので、userStruct1には影響しない
userStruct2.age = 32
print(userStruct1.age) // 30
print(userStruct2.age) // 32
var userClass1 = UserClass(age: 30)
var userClass2 = userClass1
// クラスは参照型なので、userClass1に影響する
userClass2.age = 32
print(userClass1.age) // 32
print(userClass2.age) // 32
構造体では値参照なので別にコピーされており、元のデータを書き換えることはありません。一方で、クラスの場合参照型なので元の値が書き換えられています。
以上、Swiftの値渡しと参照渡しについて解説しました。普段から特別意識する必要はありませんが、概念自体は知っておいた方が良いものです。
▼Swift関連の記事一覧
1, 【Swiftのフリーランス案件情報付き】仕事やエンジニアの将来性・学習方法!
2, 繰り返し処理に使えるSwiftのfor文とfor-in文の便利な使い方まとめ
3, 条件分岐に便利なSwiftのSwitch文の使い方まとめ
4, アプリ開発でよく使うSwiftの4つの文法を解説します
5, Swiftのoptional型を使いこなすための7つのポイント
6, Swiftで文字列を扱うためのstring型の使い方
7, Swiftでの配列の宣言・初期化・代入・参照の方法まとめ
8, 実際の開発現場でのSwiftの変数・定数の使われ方を解説します
9, Swiftでif let文を使って出来ることとguard letの使い分けに関して
10, 開発現場でよく使うSwiftのif文の条件分岐をまとめました
11, SwiftにおけるTupleの使い方とわかりやすく解説します
12, 初心者にオススメのSwiftのサンプルコードをまとめてみました
13, SwiftのString、Int、Doubleの型の変換方法をまとめました
14, 開発現場で役に立つSwiftのクロージャの使い方
15, Swiftでwhileを使って上手に繰り返し処理を行おう
16, Swiftで文字列の長さをチェックするのにlengthを使ってみよう
17, Swiftのdictionaryの使い方と初期化方法をまとめました
18,(この記事)Swiftの値渡しと参照渡しに関するまとめ
19, Swiftで参照渡ししたい時のinoutの便利な使い方
20, Swiftでfor-in文でindexを使いたい時の方法まとめ
21, Swiftでのクラスとstruct(構造体)の使い分けを解説します
人気記事