ここから本文です

ポインタ渡しと参照渡しのは何が違うの?

chi********さん

2008/10/2507:15:42

ポインタ渡しと参照渡しのは何が違うの?

ポインタ渡しと参照渡しの違いを見るために以下のプログラムを書いてみました。

#include <stdio.h>
#pragma optimize("", off)

int __stdcall func1(int *a)
{
_____asm mov eax, eax // 最適化防止

___*a *= 2;
___return *a;
}

int __stdcall func2(int &a)
{
_____asm mov ecx, ecx // 最適化防止

___a *= 2;
___return a;
}

int main()
{
___int v1 = 4;
___int r1;
___int v2 = 8;
___int r2;

___printf("v1 before:%d\n", v1);

___r1 = func1(&v1);
___// 上の行の逆アセンブル・・・
___// lea ecx,[v1]
___// push ecx
___// call func1 (401000h)
___// mov dword ptr [r1],eax


___printf("r1: %d, v1 after:%d\n", r1, v1);


___printf("v2 before:%d\n", v2);

___r2 = func2(v2);
___// 上の行の逆アセンブル・・・
___// lea edx,[v2]
___// push edx
___// call func2 (401020h)
___// mov dword ptr [r2],eax

___printf("r2: %d, v2 after:%d\n", r2, v2);
___return 0;
}

逆アセンブリみる限り、使用レジスタの違いはあれど、func1とfunc2の呼び出し方は全く一緒だし、func1とfunc2関数本体のアセンブリコードに至っては、最適化防止の一行を除き、全く同じものになっていました。これは、アセンブリレベルではポインタ渡しも参照渡しも全く違いはなく、単なるコーディングの表記上の問題に過ぎない、と認識していいのでしょうか?それとも、もっと複雑なコードになれば何か違いが出てくるのでしょうか?

Cでポインタ渡しに慣れている身としては、C++で参照渡しを使う理由が理解し難いです。なぜ、参照渡しを使うのでしょうか?

閲覧数:
38,627
回答数:
5

違反報告

ベストアンサーに選ばれた回答

kei********さん

編集あり2008/10/2618:42:56

ポインタ渡しとは、「値渡し」そのものです。渡される値が(ポインタの値なのですから)「アドレスとして意味を持っていて、アドレスとして以外の意味を持たない値」という点に着目し、他のケースの「値渡し」と区別してポインタ渡しと称しているだけです。これを踏まえて以下を読んでください。

>アセンブリレベルではポインタ渡しも参照渡しも全く違いはなく
そのとおりです。これは両者共にその目的が「相手にアドレスを渡す」という点で同一だからです。違うのは「対象となるオブジェクトのアドレスをどうやって知るか?」という点のみです。

>なぜ、参照渡しを使うのでしょうか?
時と場合によっては、それ以外にアドレスを渡す方法がないからです。
呼び出す側で対象となるオブジェクトへアクセスするのにポインタを使用していなければ、そもそも渡すべきポインタが存在しないのですからポインタ渡しはできません。だからといって対象となるオブジェクトのアドレスを得て一時的にポインタに収納するのも無駄な作業です。ですから、必然的に参照渡しを行うことになります。
逆に、new演算子によって動的に生成されたオブジェクトには参照名なんてありませんから、参照渡しはできません。この場合はnew演算子で得たアドレスを収納したポインタの値を渡すしかありません。

質問した人からのコメント

2008/11/1 00:18:07

成功 結局は記述表記上の都合のようですね・・・
他のみなさまも、ご回答ありがとうございました。。。

ベストアンサー以外の回答

1〜4件/4件中

並び替え:回答日時の
新しい順
|古い順

wat********さん

2008/10/2512:19:24

参照が内部的にはポインタで実装されていることは自然だと思いますし,おそらく広く使われている方法だろうと思います。
ただ,ポインタではNULLを渡すことができますが,参照ではそれにあたることができないなど,言語仕様上での違いはあります。

gen********さん

2008/10/2512:17:52

参照渡しをすると、呼び側からは値渡しと区別がつかなくなりかえって分かりにくくなります。通常の関数で参照を使うことはありません。ところが、参照がないと困る場面があります。それはクラスの代入演算子やコンストラクタです。

C言語で代入文ではこんな記述ができますよね。
x = y = z;

これは x =z, y=z を意味します。独自に作ったクラスでこれを実現するのに参照が必要になってきます。

class A
{
int a;
A& operator=(const A& a) { this->a = a; return *this; }
}

ポインタで実装すると、
class A
{
int a;
A* operator=(const A* pa) { this->a = *pa; return this; }
}

代入文は
x = &y;
とおかしい記述になってしまいます。これが値の代入文とは見えませんよね。それで参照がでてきたわけです。

hyv********さん

2008/10/2511:38:48

同じだと思います。
質問者様の書いてあるとおり、表記上の問題かと思ってますが(^^;

私もC/C++/VCを使ってますが参照渡しはやってません。
その変数が引数として渡されたのかどうか、ぱっと見で判別できないので。

lam********さん

2008/10/2509:12:32

参照も結局は別の変数と同じ場所を指すために使うものですから同じです。
ポインタの場合は、そのアドレスに格納されている値を変更するためにはアスタリスク(*)を使ってアクセスしなければならないので面倒ですしプログラムが読みにくくなりませんか?
ポインタと同じ働きをしてアスタリスクなしでアクセスできる参照を使った方がプログラムが綺麗になります。JavaやC#でアドレスを意識せずにプログラミングができるのは参照があるからで「ポインタがない」という理由ではありません。

あわせて知りたい

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる