おしらせ!

2018.10.16 ちょっとレイアウト変えた!

おすすめアイテムなど!

2014年12月9日

「値、参照」の「値渡し、参照渡し」の違いについて Swift でお勉強してみる

追記

2015.3.17 ちょっとコードを書き換えてみた( ˘ω˘)φ_
2016.3.27 Swift 3.0 で var宣言 が廃止されるぽい(+'-')φ_
2017.2.09 ちょっとコードを書き換えてみた( ˘ω˘)φ_



たまに uwsc を使う程度のプログラミング力なのでこの辺のことが実感できません(´ω`)
というわけで Swift でちょっとお勉強してみました。

参考りんく

<値型>と<参照型>、<値渡し>と<参照渡し>がそろってる言語で実行例を出す(Swift編)
https://qiita.com/koher/items/79fa03a472349a123ae8

こちらを参考にしたほうがよいと思います|ω・´)

こ ち ら を 参 考 に し た ほ う が よ い と 思 い ま す !( ・`ω・´)

ちなみにC言語版やPHP版もありました(+'-')b

書き直してみた

英語だらけで頭が痛くなってきたので、Xcode6 の Playground を使ってみるのもかねて自分なりに書き直してみた。Swift は日本語が使えるのがいいですなぁ~(´∀`)φ_

ちなみにコメントもいろいろ書いてみたけど、考え方があってるのかはよく分からんのであまり参考にしないでください( ´ー`)y-


※公開状態にしたらコメントがめっちゃずれたwww
 →テキストエディタに貼り付けると問題なし。
 さてどうしたものか…(´ω`).oO(とりあえず放置)

2016.3.27 追記

 Swift 3.0 で var宣言が廃止されるぽいから、下記コードを PlayGround に貼り付けてもエラーが出るかも。


//struct - 値型
struct 構造体 {
    var 量 = 0
}

var 牛乳 = 構造体(量: 1)
var 珈琲 = 構造体(量: 2)


//値渡し(var宣言すると、関数内で引数の値の変更可能になるというだけ) ※Swift3.0で廃止予定!
func 入れ替える(var コピーされた飲物1: 構造体, var コピーされた飲物2: 構造体) {
                                            //「飲物1,飲物2,飲物3」の量
    var コピーされた飲物3 = コピーされた飲物1   // 1, 2, 1
    コピーされた飲物1 = コピーされた飲物2       // 2, 2, 1
    コピーされた飲物2 = コピーされた飲物3       // 2, 1, 1
    コピーされた飲物3.量 *= 100               // 2, 1, 100
}

入れ替える(牛乳, コピーされた飲物2: 珈琲)        //値渡し(コピー)なので、元の変数は変わらない
print("\(牛乳.量)、\(珈琲.量)")               // 1, 2(そのまま!)


//inout引数(値呼びの結果返し(≒参照渡し))
func 入れ替える(inout 飲物1: 構造体, inout 飲物2: 構造体) {
                        //「飲物1,飲物2,飲物3」の量
    var 飲物3 = 飲物1   // 1, 2, 1
    飲物1 = 飲物2       // 2, 2, 1
    飲物2 = 飲物3       // 2, 1, 1
    飲物3.量 *= 100     // 2, 1, 100(この値が呼び出し元に反映する)
}

入れ替える(&牛乳, 飲物2: &珈琲)     //in-out引数は & を付けて区別
print("\(牛乳.量)、\(珈琲.量)")    // 2, 1(入れ替わる!)

//class - 参照型
class クラス {
    var 量 = 0
}

var 酒 = クラス()   //init がないから「クラス(量:1)」はダメ(構造体は自動で生成される)
var 水 = クラス()
酒.量 = 1           //init 書けとは突っ込まない|ω・)
水.量 = 2


//参照の値渡し ※Swift3.0で廃止予定!
func 入れ替える(var 参照している飲物1:クラス, var 参照している飲物2:クラス) {
                                            //「飲物1,飲物2,飲物3」が指しているもの
    let 参照している飲物3 = 参照している飲物1   // 酒, 水, 酒
    参照している飲物1 = 参照している飲物2       // 水 ,水, 酒
    参照している飲物2 = 参照している飲物3       // 水 ,酒, 酒
    参照している飲物3.量 *= 100               // 水 ,酒*100, 酒*100    //参照先の「酒」自体を100倍しているので「飲物2」にも影響する
    
    //値渡し(コピー)なので、この引数自体は呼び出し元に反映しない。
    //しかし「酒」自体は「*100」されてるので…。
    
    //一応確認してみた
    print("\(参照している飲物1.量)、\(参照している飲物2.量)、\(参照している飲物3.量)")    //2,100,100
}

入れ替える(酒, 参照している飲物2: 水)
print("\(酒.量), \(水.量)")      // 100, 2(酒の量が100倍されている!)



//上で値が変更されたので元に戻しておく(/ω\)
酒.量 = 1
水.量 = 2



//inout引数(値呼びの結果返し(≒参照渡し))
func 入れ替える(inout 参照している飲物1:クラス, inout 参照している飲物2:クラス) {
                                            //「飲物1,飲物2,飲物3」が指しているもの
    let 参照している飲物3 = 参照している飲物1   // 酒, 水, 酒
    参照している飲物1 = 参照している飲物2       // 水, 水, 酒
    参照している飲物2 = 参照している飲物3       // 水, 酒, 酒
    参照している飲物3.量 *= 100               // 水, 酒*100, 酒*100(この値が呼び出し元に反映する)
    
    //一応確認してみた
    print("\(参照している飲物1.量)、\(参照している飲物2.量)、\(参照している飲物3.量)")    //2,100,100
}

入れ替える(&酒, 参照している飲物2: &水)
print("\(酒.量), \(水.量)")                 // 2, 100  ( =д=).oO(ややこしいでござる)



Swift めも

詳しくは wiki を見たほうがよいと思います!ヽ(`Д´)ノ
Swift (プログラミング言語) - Wikipedia
https://ja.wikipedia.org/wiki/Swift_(プログラミング言語)

構造体(値型)・クラス(参照型)の違い

構造体は「値型/value type」
let や var でアサインされる時に"コピー"される。
これに属する物としては「String,Array,Dictionary」がある。

クラスは「参照型/reference type」
アサインされる時には"参照ポインタ"が渡される。

値渡し

関数の引数はデフォルトではlet(定数)。
var 付けて引数を宣言すると、その引数は関数内で値を変更できるようになる。

どちらの場合も、引数は"値渡し"。呼び出し元の変数の値は変わらない

in-out引数(≒参照渡し)

inout を付けて引数を宣言すると、引数に値のコピーが渡り、
関数を実行した結果の値がコピーされて呼び出し元に書き戻される
いわゆる"値呼びの結果返し(call-by-value-result)"となる。

呼び出し側では in-out 引数に渡す変数名の前に & を付ける。

いやらしい…

にんきの とうこう(/ω\).oO(過去30日間)

あーかいぶ

れんらく ふぉーむ(試運転中)

名前

メール *

メッセージ *

ヽ(´ー`)ノ