swiftの参照渡しができなくて困っております。

Writer: admin Type: sudam Date: 2019-01-22 00:00
swiftの参照渡しができなくて困っております。func sayHello(msg:inout String){var msg = msgmsg += "!!"print(msg)}var message = "Hello"sayHello(msg : &message)print(message)としているのですが、messageの値の中身が変わらずHelloのままです。どこがいけないのでしょうか。共感した0###プログラムの作成環境、プログラムの実行環境を明記してください。例えば、「Xcode 10.1、iOSシミュレータ10.1のiPhone XR 12.1」というように。Xcode 10.1のPlaygroundを使って、下記のプログラムを実行してみました。func sayHello(msg: inout String) { msg += "!!"}var message = "Hello"sayHello(msg: &message)print(message)結果は、「Hello!!」となり、意図どおりになりました。また、ビルド時になにも注意喚起(黄色アイコン)、コンパイルエラー(赤色アイコン)は出ていません。※ここから先は、ご質問と無関係な内容になるので、無視していただいてかまいませんが、質問者さんが、Swiftを使ったプログラミングと、iOSアプリの開発を続けようという意思を持っているのであれば、「なんでそんなことも知らないんだよ!」といつか指摘されるであろう事柄なので、まあ、読んでおいたほうが吉です。Swiftで使われる「inout」という修飾子は、C言語の、引数にポインタを渡す関数のスタイルをブリッジするために用意されたものですが、Swiftという言語自体は、「参照渡し」はある目的以外では使わず、「値渡し」を行うことが前提になっています。それは、C言語が開発、制定された時代のハードウェア環境と、Swiftが開発、制定された時代のハードウェア環境の違いに由来します。C言語が制定され積極的に使われた時代は、1MBのRAM(メモリ)が1万円以上していました(1GBが1万円、じゃないよ)。そういうハードウェア環境では、いかにメモリの使用量を節約するかが、プログラミングにおける大事なテクニックでした。対して現在は、片手に乗るiPhoneというデバイスでさえ、GB単位のメモリを搭載する時代です。メモリを浪費することを気にすることはなく、ただプログラムの処理速度、処理効率だけを考えれば良くなりました。質問者さんが書きたいプログラムのSwift的な模範解答は、こうなります。func sayHello(msg: String) -> String { return msg + "!!"}let message = "Hello"let newMessage = sayHello(msg: message)print(newMessage)「変数message、変数newMessageのふたつを作ったら、ハードウェア(メモリ)にかかる負荷が倍になってしまう」なんてことは、考えなくていいのです。バンバン、変数を「var」でなく「let」を使っていくつも宣言してください。「Swiftにおいて、参照渡しではなく、値渡しをするのが主流である。では、なぜSwiftに参照渡しがあるのか?」それは、まあなんだかんだいってSwiftのオブジェクト指向言語だからです。クラスというオブジェクトのプロトタイプがあって、そこからインスタンスというオブジェクトを生成し、このインスタンスはほかのインスタンスと参照し合うことによって機能します。こういうオブジェクト指向の骨格を維持するため、クラスのインスタンスは参照渡しですが、クラス以外の例えば構造体(Structure)、列挙型(Enumeration)のインスタンスは値渡しです。ここらへん、クラスと構造体の使い分けというのが、じつはSwiftプログラミングの、大事なテクニックとなります。ナイス0
###無事解決致しました。詳しくいろいろと教えていただき、ありがとうございました。###もう Swift 実行環境は持ってないですし、想像です。ハズレならごめん。sayHello 関数内のvar msg = msgのせいじゃないですかね。これで、引数msgの値コピーが作られ、かつ後続コードでは msg という名前は(引数で無く)この新たなローカル変数を指すことになってしまう。この1行をとっぱらえば、msg += "!!"の対象は inout 引数となり、呼び手側の実引数に副作用をもたらすことになるんじゃないのかな。ナイス0

 

TAG