• 締切済み

参照渡しと値渡し

エクセルVBAでプログラムを色々勉強中ですが、表題の件が理解できません。 というか、ByRefとByValで動きというか、やっていることは分かるんですが、具体的な目的、使用方法、ケースが見い出せてないので、ピンときていません。 経験者の皆さんの、「どういった時にこうなってしまうので、解決方としてどっちを使った」などの具体例を教えてほしいです。 目的が分からないといまいち理解できません。 どうか宜しくお願いします。

みんなの回答

noname#212058
noname#212058
回答No.4

回答No.3 です。 > 「関数で戻り値を複数返したくなったとき」とは > 具体的にどのような時でしょうか? 例えば、郵便番号を引数で渡すと、その郵便番号の住所を返す 関数があったとします。単に住所だけを返すだけなら Function GetAddress(ByVal zipCode As String) As String で良いのですが、住所は「都道府県」と「都道府県よりも後ろ の部分」のふたつに分けて返すようにしたいとします。 この解決方法としては、以下の方策が考えられるでしょう。 A案)  戻り値を工夫して複数データを返せるようにする  配列を使う、戻り値用の構造体・クラスを作るなどなど B案)  「都道府県」を返す関数と、「都道府県よりも後ろの部分」  を返す関数を別々に作る C案)  ByRef を使って引数で返すようにする  Sub GetAddress(ByVal zipCode As String, ByRef prefecture As String, ByRef address As String) どの案を選択するかは、コーディング規約、処理効率、実装 効率、実装者の美学によって異なります。 私の経験上では ・戻り値用の構造体・クラスを作るのが面倒な場合 ・戻り値用の構造体・クラスを New するコストが処理速度上  の問題になる場合 にC案を採用することが多いです。

garigarisama
質問者

お礼

ありがとうございます。 設計のところまでご説明いただき、良く分かりました。 「zipCode」は一旦入れた値をどこの「zipCode」でも変わって欲しくないからByValで、 「prefecture」と「address」は「zipCode」から求められた値を、そのままどこの 「prefecture」と「address」でも使用したいということで、ByRefを使われているという認識で宜しいでしょうか? 説明が下手で伝わったかどうか、、、ですが宜しくお願いします。

noname#212058
noname#212058
回答No.3

○ByRef を使うケース 関数で戻り値を複数返したくなったとき。ByRef を使って引数で返す方法があります。 ○ByVal を使うケース 上記のような『明確に ByRef を使いたいケース』ではない場合は、普通 ByVal を使います。

garigarisama
質問者

お礼

ありがとうございます。 「関数で戻り値を複数返したくなったとき」とは具体的にどのような時でしょうか? どういった問題があって「関数で戻り値を複数返したくなった」のか、事例は皆さんどのようなものがあったのかを知りたかったです。 ノウハウ的なところになるかと思いますが。 ByVal を使うケースに関しては参考にさせていただきます。

  • weavaest
  • ベストアンサー率15% (157/1020)
回答No.2

参照渡しは、呼び出し元と同じデータを見ていますが、値渡しは、呼び出し元のデータをコピーしたものを見ています。 参照渡しは、呼び出し先で値を変更すれば、参照元でも値が変更されます。値渡しはそうはなりません。 もう一つ別の視点で、値渡しはコピーなので、コピー先として元のデータと同じサイズのメモリを消費します。 具体例 関数の処理で変数の内容を変更したい場合は参照渡しにする。 関数呼び出しで、変数の容量が大きくて、メモリ不足などが発生した場合は引数を参照渡しにする。

garigarisama
質問者

お礼

ありがとうございます。 本文の方は理解しています。 具体例に挙げていただいたことに関しては、参考にさせていただきます。

  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.1

値渡しと参照渡しになる理由は2つでしょう。 1.必然的になるもの 2.ある意図で行うもの 1.は次です。 引数はレジスタで与えられます。 レジスタはCPUが直接演算できるメモリです。 そのサイズは32bitマシンなら32bit、64bitマシンなら64bitです。 このサイズに収まるデータは値渡しが可能ですが、超えるものは参照渡ししか有り得ません。 数値、文字、アドレス(データとしての)などに限られます。 配列、構造体、文字列等は入らないので必然的に参照渡しです。 速度的には値渡しが直接データを使えるので望ましいでしょう。 2.は値渡しが出来るのに参照渡しにする理由、ということになります。 目的はズバリ副作用です。 関数のアウトプットは関数値だけです。 それ以外のアウトプットを関数の副作用といいます。 入力であるはずの引数の数値を書き換える、これが禁断の副作用です。 値渡しでレジスタ上のデータを書き換えても、呼び出した側には影響を受けません。 呼び出した側が参照するメモリ上のデータを置き換えるには参照渡しで、その場所を知る必要がある訳です。 安易に使える技ではなく、誰もが認める相当の理由がなければ使うべき技ではありません。 何故なら呼び出し側のデータが壊れる場合の、壊れる原因が非常に掴み難くなるからです。 関数が呼び出し側を壊すことが出来ない、という意味でも値渡しが望ましい訳です。 細かいことを書くともっと理由はありますが、以上を踏まえておけば問題無いと思います。

garigarisama
質問者

お礼

ありがとうございました。 でも、欲しかった回答とは少しかけ離れた難しいお話でした^^;

関連するQ&A