黒龍's Blog

明日から役立つ無駄知識をあなたに(仮)

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  170  : 記事  0  : コメント  2715  : トラックバック  26

ニュース

わんくま同盟に参加させていただきました。
どうぞよろしくお願いします。

自己紹介

コミュニティ

  • わんくま同盟
    わんくま同盟

書庫

自社で新人(以下フレッシュマン's)から質問を受けることがたまにあるのですがこの参照渡し、値渡しについてどうも私の認識とはズレが頻繁に起こるのでエントリしようと思います。

まず、C、C++でのポインタやC++での参照渡しなんですがフレッシュマン'sいわく「指し示すポインタが渡されるんですよね?と」この変数に対する操作は呼び出し元影響するらしい。

わし「ふむふむ。んじゃ値渡しは」

フレッシュマン's「えっと呼び出し元から呼び出し先にコピーされます。なので呼び出し先で変数を書き換えても大丈夫です」

ここでいつもぶちかましてやります。

わし「なるほどなぁ。いいか、よく聞いてくれよ。参照渡しなんてのは無いんだよ。全てコピーされるんだよ」

フレッシュマン's「けどポインタとか渡すと書きかえれますよ?」

わし「んじゃそのポインタの中身じゃなくてポインタ自身をを書き換えたらどうなんの?」

違うんです。関数の呼び出し元と呼び出し先はコピーされてるんです。ただそのコピーされた変数がポインタであれば値を見る際に指し示す先を見ることになるので同じ値が触れるんです。

どうも呼び出しのルールが2種類あるかのような理解をしているのでいつもこう説明します。引数が参照型なのか値型なのか(Cでいうならポインタ変数か普通の変数か)の違いであって呼び出し方がふたつあるんじゃないよと。

ここで誤解が含まれるとrefキーワードやらoutキーワードはどう理解するんでしょ??

(と、かましてみたはいいけど突込みが怖いなぁ・・・^^;;)

投稿日時 : 2007年7月25日 19:29

コメント

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/25 19:58 とっちゃん
C++ の参照型(&がつくやつ)は、本当に参照です。
元の値をそっくりそのまま渡すというのが一番しっくりくるイメージです。まさに「参照」。

#実際は、ポインタの特殊系と言うべき代物ですがw<怒られそうだw

ちなみに、.NET の参照型と、Native C++ の参照型は、日本語にすれば同じですけど、意味(実装)はまったく違いますw
#で、こういうこと言うと知らない人は頭抱えてしまうんだwww


# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/25 20:07 επιστημη
> C++ の参照型(&がつくやつ)は、本当に参照です。

うんうんう。
参照になりすましたポインタだけどねー♪


# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/25 20:36 シャノン
> 参照になりすましたポインタだけどねー♪

COMやってっと、REFIID(const IID &)なんか、C用のインターフェイス宣言ではポインタだしねーw

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/25 23:51 黒龍
まずC、C++とか書いたわりに他に触れずに終わってる・・・。(C#でのrefやらoutをとりあえず除外したかったわけで)
C++の参照型ですが文脈中はエイリアスの定義みたいな印象がありますね。(実装ではまんま元の値を使ったりするのかな?)
関数に渡す場合はポインタとそう区別は無いと思ってます。呼び出し先で元の値(クラス)として使えるっての参照型としての特徴かなと。
新人さんと話してて感じたのは本当に元の値が使われてるかのような話しぶり(たとえばポインタをインクリメントしたら元の値も変わるかのような)でアセンブラ>Cという風に進んだ私からはスタックにつむかレジスタにいれるかっしょ?見たいな感じで悩みようが無かったのですがいまどきの新人さんは入門書なんかの言葉を額面通り受け取っちゃうみたいです。

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 10:58 シャノン
新人さん向けの入門書にはスタックとかレジスタとか書いてないもんねぇ。

> たとえばポインタをインクリメントしたら元の値も変わるかのような

それは、配列のポインタを受け取った側で ++ したときに、呼び出し側でも位置がいっこ進む(配列ポインタの参照渡しみたいな)ってこと?
それとも、単に int 型のポインタを ++ したら、呼び出し側の int も ++ されるイメージ?
前者なら「値渡しと参照渡し」として論じるべきだけど、後者はそれ以前に「実体とポインタ」の区別がついてないんじゃないだろうか。

前者:
int hoge[] = { 1, 2, 3 };
foo( hoge );
int i = *hoge; // i == 2? No!

void foo( int * phoge ) { ++phoge; }

後者:
int hoge = 1;
foo( &hoge );
int i = *hoge; // i == 2? No!

void foo( int * phoge ) { ++phoge; }

で、C++ の参照も ref も out も、実装はポインタの値渡しなんだろうけど、渡された方ではポインタ自体の書き換えができないという点では、意味的には値渡しとは別の「参照渡し」と呼んでもいいかも。

# リモーティングでマーシャリングが絡むとまたぐるぐるに…w
# 渡した側と受け取った側のポインタ値が違うこともよくある。
# プロセス空間はおろか、マシンさえ違う場合があるからねぇ。

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 11:07 Chuki
>Cという風に進んだ私からはスタックにつむかレジスタにいれるかっしょ?

そこで、次の大阪勉強会では各言語系の実装差異をとっちゃんさんがディープに話していただけるんですね wktk^^

できれば、VBな人にLetとSetの違いとか、ActiveX ExeのByRefなんてところまで...
#と自分の趣味に引き込んでみる^^;

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 11:18 黒龍
えとコメしたのは前者のイメージですね。メモリ上の位置が進むという感じ。

# リモーティングでマーシャリングが絡むとまたぐるぐるに…w
# 渡した側と受け取った側のポインタ値が違うこともよくある。
# プロセス空間はおろか、マシンさえ違う場合があるからねぇ。
ですね。強調したいのは渡すものが参照系か実値系かの違いだけで呼び出しの仕組みは変わらないんだよということです。
(この例はナイスですね。すごくわかりやすい)

どうもこのあたりの勘違いとともに=の受け取り方も関係してそうです。
プログラムでの=というのは代入であってコピーの作成なんですがどうも数学的な同値と捉えているようでその誤解の延長で参照渡しは同じものを使っていると言う理解のようです。

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 14:34 とっちゃん
>各言語系の実装差異
いや、やらん!w
基本は、C/C++(ネタ的には、++ の部分は入れないつもりだったけど、参照型(&のつくやつ)はあってもいいかもしれない...w)だしw

そもそもが、型とはとかインスタンスがとかじゃないし、値型、参照型ではなくて、スタックとヒープだしw

基本的には庄屋(アロケータ)と、畑(ヒープ)と小作(参照元の実体)だからねw
小作としては、いかに庄屋の機嫌を損ねることなく畑を借りるか?
と言うお話になる...

はずw<おい!


>ActiveX ExeのByRefなんてところまで
ここは COM だからおいらじゃなくてシャノンさんだw

がっつりお願いしましょうwww


# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 14:41 刈歩 菜良
おっ!
わたしのセッションで出てくるネタだ(たぶん来週)。
でも、コメントが多すぎて全部読んでる暇ないよぉ!

またあとで読んだらコメントします。(ってコラッ

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 14:51 刈歩 菜良
読んだ!

まず、C++でいうと、関数呼び出し時の渡し方って3パターンなることになってる(コーディングスタイル上)。
・値渡し
・ポインタ渡し
・参照渡し
で、イメージで言うと黒龍さんの言う通り、値渡しとポインタ渡しは結局はものをコピーで渡しているので、「渡し方」において違いはない。
でも、参照渡しはそれでは説明がつかないので、私の場合は「同じ領域に別名がつくんだよ」と説明します。

でも、実装はεπιさんのおっしゃる通り、ポインター渡しで実装されている。表面上のコーディングスタイルが違うだけ。
しかし、新人ちゃんにそんなことを言っても混乱するだけなので、ここは内緒にします。

で、C#の場合は初心者にはrefとかoutとか教えません。
だから、渡すものが値型だろうが参照型だろうが「渡し方」は同じく「コピー」渡し。
そこをしっかり押さえておけば、ゆくゆくのrefとかoutの理解が早いのだと思いますし、混乱も少ない。

わかってないうちにrefとかoutとか考えちゃうとわけわかんなくなっちゃう。

と、いう話も来週のセッションでお話しするので、記事にせず、こっそりコメントにとどめます。
(^.^)

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 15:08 とっちゃん
>記事にせず、こっそりコメント
あはは。
おいらは、それを受けてから、ネタの絞り込みをします<おい!

いや、それまでにあげないといけないネタが...w
#そっちのほうが大変なのよwww

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 16:13 シャノン
> ActiveX ExeのByRefなんてところまで

ActiveX は COM じゃありません(w

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 16:29 とっちゃん
OLE?

# re: 参照渡しなど無いのだよ!(と、誤解を恐れず書いてみる) 2007/07/26 18:48 刈歩 菜良
COM+?

Post Feedback

タイトル
名前
Url:
コメント