値渡し、参照渡し、ポインタ渡しを議論する

このエントリーをはてなブックマークに追加
84デフォルトの名無しさん:2006/05/06(土) 11:19:19
>>82
オブジェクト型なんて、まさにそれをやってるわけで
85デフォルトの名無しさん:2006/05/06(土) 11:23:43
>>83
サンクス。
やっと理解できました。
86デフォルトの名無しさん:2006/05/06(土) 11:51:26
C++ におけるポインタと参照の違い

参照 ポインタ演算ができない
ポインタ ポインタ演算ができる
※ポインタ演算が不要なら参照がお勧め

参照 アドレスの比較をするために & を使わなければならない
ポインタ そのまま比較できる
※NULL を渡したり返したりするならポインタがお勧め
87デフォルトの名無しさん:2006/05/06(土) 13:11:00
NULL渡すな。
optional使え。
88デフォルトの名無しさん:2006/05/06(土) 19:46:30
>>87
何気に参照型も受け付けるのは驚いた。
89デフォルトの名無しさん:2006/05/07(日) 14:19:33
世の中には、NULLを返せる参照もあるし、
ポインタ演算は、イテレータや参照の配列で
同じことやさらに高度なことが出来る。
90デフォルトの名無しさん:2006/05/07(日) 15:49:50
ポインタ渡し
┣2つ目以降の返値の代用(→boost::tupple)
┣配列(→各種iterator)
┣省略可能(→boost::optional)
┣渡したオブジェクトの状態を変化させる(→参照)
┗外部ライブラリから返ってくるハンドル(→ラップしる!)

という風に、C++ではポインタ同様にポインタ渡しも排除できると思う。
91デフォルトの名無しさん:2006/05/07(日) 17:21:49
この手のスレは参照をC/C++前提で話す人と
一般的な参照で話す人とで齟齬が生じるんだよな
92デフォルトの名無しさん:2006/05/07(日) 18:04:07
関係ないけど、こないだ読んだ本では、参照渡しも
結局はビットフィールドコピーしてるんだから値渡しだ!ってゆってた
93デフォルトの名無しさん:2006/05/07(日) 19:44:14
おおぅ何か香ばしいぜぇぇえええ
94デフォルトの名無しさん:2006/05/07(日) 19:45:07
それはアドレスがコピーされてるってことでしょ。
95デフォルトの名無しさん:2006/05/07(日) 20:25:02
結局、プログラムも、音楽も、映像もビットフィールドで出来ているんだから、
二進数だ!
96デフォルトの名無しさん:2006/05/07(日) 22:03:39
>>74
C++の参照渡しはコピーコンストラクタや演算子のオーバーロードのために存在する。
特に、コピーコンストラクタは参照渡しで定義しないと自動的に無限ループだからね。

個人的には、これら以外では参照渡しよりもポインタ渡しを推奨するなあ。
ソースを書いてるときはポインタ渡しの方がタイプ量が若干増えるけど、
後からソースを見たときに、実際に渡しているのが何なのかが
パッと見て区別できるのは結構大きい。

特に「ポインタ不要論」で紹介されている、データの返し先引数として
参照を使うってのは、俺的には最悪。
例えばf(a,b,c,d,e)の呼び出しだけ見てa・b・cは値を渡すだけで
d・eには値が帰ってくるかもしれない、なんてパッと見で分かる奴なぞ
だれもいないだろう。
ポインタにすれば、printf("%d",a)とscanf("%d",&a)の例のように
前者はaを書き換えない、後者はaを書き換える(かもしれない)ってのが
一目瞭然。
97デフォルトの名無しさん:2006/05/07(日) 22:49:21
>>96
その理屈だと、巨大なオブジェクトや構造体も値渡しということになってしまう。
かといって、ポインタ渡ししたくても書き換える可能性ありと思われてしまうことになる。

結論:適材適所。他人に公開する関数はI/Fの記述を忘れずに。
98デフォルトの名無しさん:2006/05/07(日) 22:54:22
俺はデータの返し先に参照を使うことに抵抗を感じないけどな。
std::string s;
std::getline(std::cin, s);
使ったときは大抵こういう風に直前に変数宣言があって、
明らかにgetlineの中でsに何か書かれるに違いないという感じになる。

それにそう何個も返したければ戻り値クラス・構造体にまとめるし。
99デフォルトの名無しさん:2006/05/07(日) 23:42:07
96じゃないけど、const参照渡しはありだとおも。
行き→&無し
帰り→&あり
で統一するなら。
まー漏れはtupple使うがなー
100デフォルトの名無しさん:2006/05/08(月) 11:49:31
>>96
>C++の参照渡しはコピーコンストラクタや演算子のオーバーロードのために存在する。
デタラメを吹聴しないように。

>ポインタにすれば、printf("%d",a)とscanf("%d",&a)の例のように
  char s[] = "1234";
  myfunc("%s", s);
*s を書き換えるかどうか、お前には想像がつくとでも?
それは、ポインタか参照か、という問題ではない。
ポインタ/参照を受け取る関数が、その内容を
書き換えるかどうかは、const として宣言されているか
どうかで判断するしかない。
101デフォルトの名無しさん:2006/05/08(月) 18:46:16
>>100
D&Eには「主に、演算子のオーバーロードをサポートするために導入した」と書かれている。
だからと言って俺はこれっぽっちもそれ以外の用途で非const参照を使うべきではないと思っていないけどね。
102デフォルトの名無しさん:2006/05/09(火) 16:01:15
>2は概念と実装がごっちゃだよ。

概念としては値渡しと参照渡ししかない。
(名前渡しはちょっと複雑な参照渡し)
実装としては値渡ししかない。
(スタックで渡すか固定アドレスで渡すかレジスタで渡すか等の違いはある)

Cのポインタ渡しはプログラマが、C++等の参照渡しはコンパイラが
値渡しを使って擬似的に参照渡しを行っているだけ。
103デフォルトの名無しさん:2006/05/09(火) 22:44:12
>>102最後の行は
概念と実装がごっちゃでないのか?
104102:2006/05/09(火) 23:12:30
>103
値渡しを用いて参照渡しを実装している、というべきだったかな。
105デフォルトの名無しさん:2006/05/10(水) 02:42:53
■値渡し func(i)
push dword ptr[ebp-04]
call func1
■参照渡し func2(i)
lea eax,[ebp-04]
push eax
call func2
■ポインタ渡し func3(&i)
lea eax,[ebp-04]
push eax
call func3
106デフォルトの名無しさん:2006/05/11(木) 14:11:04
>>105
お、参照とポインタ渡しはコンパイル結果が同じだね?
107デフォルトの名無しさん:2006/05/11(木) 18:22:03
■値渡し func(i)
push dword ptr[ebp-04]
call func1
■参照渡し func2(i)
lea eax,[ebp-04]
push eax
call func2
■ポインタ渡し func3(&i)
lea eax,[ebp-04]
push eax
call func3
■ポインタ渡し func4(i)
push dword ptr[ebp-04]
call func4
108デフォルトの名無しさん:2006/05/12(金) 09:06:52
同じようなソースでも
コンパイル後が違ったり同じだったりするところが
面白いというかイヤらしいというか。
109デフォルトの名無しさん:2006/05/12(金) 12:49:12
>>106
当たり前だろう。
110デフォルトの名無しさん:2006/05/12(金) 12:53:13
>>107
func2(i)とfunc3(&i)ってeaxに一度アドレス入れてるのって何か無駄じゃない?
111110:2006/05/12(金) 12:55:33
無駄じゃなかったww
112デフォルトの名無しさん:2006/05/12(金) 18:00:05
名前渡しは?
113デフォルトの名無しさん:2006/05/17(水) 10:51:16
名前渡しってC++で実装できなくもなさそうだよな。

template <class T> struct named_arg {
 virtual T operator() () = 0;

 named_plus<T> operator+ (const named_arg<T>& t1) {
  return named_plus<T>(*this, t1);
 }
//以下演算子をオーバーロードしまくり
};

template <class T> class named_plus : named_arg<T> {
 const named_arg<T>& _t1, _t2;
public:
 named_plus(const named_arg<T>& t1, const named_arg<T>& t2>)
  : _t1(t1), _t2(t2) {}
 T operator() () { return _t1() + _t2(); }
};

template <class T> class named_element : named_arg<T&> {
 T& _tref;
public:
 named_element(T& tref) : _tref(tref) {}
 T& operator() () { return _tref; }
};

…何に使うんだ?
114デフォルトの名無しさん:2006/05/18(木) 01:37:55
普通にマクロでいいじゃん
115デフォルトの名無しさん:2006/08/16(水) 01:03:55
C++の場合、全部参照にすべき(Javaがそうだからそろえる

test1(int& a){ //参照渡し
a = 1;
}
test2(int* a){ //ポインタ渡し
*a = 1;
}
test1(a);
test2(&a); //結果は同じだが、書き方が2種類でミスがでる

要はポインタ表記を絶滅させること。これでヌルポもなくなる。
あと文字列はstd::stringとかCStringでもいい
配列はvectorでnew、deleteもなくなってメモリリークもなくなる
116デフォルトの名無しさん:2006/08/16(水) 10:44:19
>>115
つまり、巨大な単体オブジェクトも常にローカルに配置しろと言うことですね?
或いはレガシーなAPIとのI/Fを捨てると言うことですね?
117デフォルトの名無しさん:2006/08/16(水) 12:49:23
>>115
本筋には賛成するが、Javaがそうだからというのは違和感を感じる。
C++の参照は後から参照先を変えられないが、Javaの参照ではできる。
その点ではポインタの方が近い。

>>116
どっちもラッピングすればいいと思う。

特に前者に関してはこういう話も。
http://d.hatena.ne.jp/Cryolite/20060622
118デフォルトの名無しさん:2006/08/24(木) 22:57:36
//やっぱ邪悪杉
int procA()
{
    printf("Hello World!\n");
    return 0;
}

int main(int argc, char* argv[])
{
    int (*funcptr)()=procA;

    (*&*&*&****&**&*******&*&*&*&***&***&***&**&***&**&***&*&**procA)();
    (*&*&*&****&**&*****&*&***&*&**procA)();

    return 0;
}



119デフォルトの名無しさん:2006/08/24(木) 22:58:42
間違えた
int procA()
{
printf("Hello World!\n");
return 0;
}

int main(int argc, char* argv[])
{
int (*funcptr)()=procA;

(*&*&*&****&**&*****&*&***&*&**funcptr)();
(*&*&*&****&**&*******&*&*&*&***&***&***&**&***&**&***&*&**procA)();

return 0;
}

120デフォルトの名無しさん:2006/08/28(月) 17:23:46
ヌルポが出ること事態ヘタレの象徴だと思ってる俺がいる
121デフォルトの名無しさん:2006/09/05(火) 05:07:28
>>119
昔まじめに

int********** GetHoge();

みたいな関数見たことあるよw
一瞬何の言語かと思った
122デフォルトの名無しさん:2006/09/05(火) 23:55:56
>>121
ま、糞だな
123デフォルトの名無しさん:2006/09/16(土) 19:50:31
多次元の配列だろうな。
124デフォルトの名無しさん:2006/09/25(月) 09:41:03
何次元だよwwww
メモリ足りんのか?
125デフォルトの名無しさん:2006/10/29(日) 23:05:24
ttp://homepage3.nifty.com/mogami/diary/d0610.html#26t1
> ...
> だからユーザからはポインタの自由を取り上げるべきだ。
126デフォルトの名無しさん:2006/10/30(月) 00:48:06
>>125
ユーザーにはプログラム自体見せるなよw
127デフォルトの名無しさん:2006/10/30(月) 00:58:13
「プログラミング言語のユーザ」という意味だと思われ
128デフォルトの名無しさん:2006/10/30(月) 08:55:25
>>125
その言語のページは無いの? ひどく検索しづらいんだけど。
129デフォルトの名無しさん:2006/10/30(月) 09:09:13
プログラミング言語 Cipher
ttp://homepage3.nifty.com/mogami/lang/index.html
130デフォルトの名無しさん:2006/10/31(火) 01:58:26
ありがと
面白そうかも
131デフォルトの名無しさん:2006/11/26(日) 16:10:22
どうでもいいが、C++を前提にすれば参照はインライン展開される際ポインタと違って
演算される可能性が無いので処理系によってはマクロ展開のように呼び出しもとの変数
そのものに差し替えられる可能性がある。また、ポインタの場合は演算される可能性が
あるので大抵一時変数が確保される。尤も、参照渡しの最たる所はテンプレートで既存
の型と演算子をオーバーロードされたクラスが同居できる点にあるが…。
132デフォルトの名無しさん:2006/11/26(日) 16:41:52
>>131
今時のコンパイラはインライン展開できる状況ならポインタでもconst修飾されていれば参照と同じようなコードになるよ。
133デフォルトの名無しさん
Cのポインタは難しいといわれてきたが、概念的には気楽だと思う。
所詮は相対アドレスだし、デバッガも充実してるからね。
自分にはperlやJavaScriptのほうがヤダ。
特にデバッガを通すと挙動が変わるperlには殺意を覚える。