>>82 オブジェクト型なんて、まさにそれをやってるわけで
C++ におけるポインタと参照の違い
参照 ポインタ演算ができない
ポインタ ポインタ演算ができる
※ポインタ演算が不要なら参照がお勧め
参照 アドレスの比較をするために & を使わなければならない
ポインタ そのまま比較できる
※NULL を渡したり返したりするならポインタがお勧め
NULL渡すな。
optional使え。
世の中には、NULLを返せる参照もあるし、
ポインタ演算は、イテレータや参照の配列で
同じことやさらに高度なことが出来る。
ポインタ渡し
┣2つ目以降の返値の代用(→boost::tupple)
┣配列(→各種iterator)
┣省略可能(→boost::optional)
┣渡したオブジェクトの状態を変化させる(→参照)
┗外部ライブラリから返ってくるハンドル(→ラップしる!)
という風に、C++ではポインタ同様にポインタ渡しも排除できると思う。
この手のスレは参照をC/C++前提で話す人と
一般的な参照で話す人とで齟齬が生じるんだよな
関係ないけど、こないだ読んだ本では、参照渡しも
結局はビットフィールドコピーしてるんだから値渡しだ!ってゆってた
93 :
デフォルトの名無しさん:2006/05/07(日) 19:44:14
おおぅ何か香ばしいぜぇぇえええ
それはアドレスがコピーされてるってことでしょ。
結局、プログラムも、音楽も、映像もビットフィールドで出来ているんだから、
二進数だ!
>>74 C++の参照渡しはコピーコンストラクタや演算子のオーバーロードのために存在する。
特に、コピーコンストラクタは参照渡しで定義しないと自動的に無限ループだからね。
個人的には、これら以外では参照渡しよりもポインタ渡しを推奨するなあ。
ソースを書いてるときはポインタ渡しの方がタイプ量が若干増えるけど、
後からソースを見たときに、実際に渡しているのが何なのかが
パッと見て区別できるのは結構大きい。
特に「ポインタ不要論」で紹介されている、データの返し先引数として
参照を使うってのは、俺的には最悪。
例えばf(a,b,c,d,e)の呼び出しだけ見てa・b・cは値を渡すだけで
d・eには値が帰ってくるかもしれない、なんてパッと見で分かる奴なぞ
だれもいないだろう。
ポインタにすれば、printf("%d",a)とscanf("%d",&a)の例のように
前者はaを書き換えない、後者はaを書き換える(かもしれない)ってのが
一目瞭然。
>>96 その理屈だと、巨大なオブジェクトや構造体も値渡しということになってしまう。
かといって、ポインタ渡ししたくても書き換える可能性ありと思われてしまうことになる。
結論:適材適所。他人に公開する関数はI/Fの記述を忘れずに。
俺はデータの返し先に参照を使うことに抵抗を感じないけどな。
std::string s;
std::getline(std::cin, s);
使ったときは大抵こういう風に直前に変数宣言があって、
明らかにgetlineの中でsに何か書かれるに違いないという感じになる。
それにそう何個も返したければ戻り値クラス・構造体にまとめるし。
96じゃないけど、const参照渡しはありだとおも。
行き→&無し
帰り→&あり
で統一するなら。
まー漏れはtupple使うがなー
>>96 >C++の参照渡しはコピーコンストラクタや演算子のオーバーロードのために存在する。
デタラメを吹聴しないように。
>ポインタにすれば、printf("%d",a)とscanf("%d",&a)の例のように
char s[] = "1234";
myfunc("%s", s);
*s を書き換えるかどうか、お前には想像がつくとでも?
それは、ポインタか参照か、という問題ではない。
ポインタ/参照を受け取る関数が、その内容を
書き換えるかどうかは、const として宣言されているか
どうかで判断するしかない。
>>100 D&Eには「主に、演算子のオーバーロードをサポートするために導入した」と書かれている。
だからと言って俺はこれっぽっちもそれ以外の用途で非const参照を使うべきではないと思っていないけどね。
>2は概念と実装がごっちゃだよ。
概念としては値渡しと参照渡ししかない。
(名前渡しはちょっと複雑な参照渡し)
実装としては値渡ししかない。
(スタックで渡すか固定アドレスで渡すかレジスタで渡すか等の違いはある)
Cのポインタ渡しはプログラマが、C++等の参照渡しはコンパイラが
値渡しを使って擬似的に参照渡しを行っているだけ。
>>102最後の行は
概念と実装がごっちゃでないのか?
104 :
102:2006/05/09(火) 23:12:30
>103
値渡しを用いて参照渡しを実装している、というべきだったかな。
■値渡し 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
>>105 お、参照とポインタ渡しはコンパイル結果が同じだね?
■値渡し 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
同じようなソースでも
コンパイル後が違ったり同じだったりするところが
面白いというかイヤらしいというか。
>>107 func2(i)とfunc3(&i)ってeaxに一度アドレス入れてるのって何か無駄じゃない?
111 :
110:2006/05/12(金) 12:55:33
無駄じゃなかったww
名前渡しは?
名前渡しって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; }
};
…何に使うんだ?
普通にマクロでいいじゃん
C++の場合、全部参照にすべき(Javaがそうだからそろえる
例
test1(int& a){ //参照渡し
a = 1;
}
test2(int* a){ //ポインタ渡し
*a = 1;
}
test1(a);
test2(&a); //結果は同じだが、書き方が2種類でミスがでる
要はポインタ表記を絶滅させること。これでヌルポもなくなる。
あと文字列はstd::stringとかCStringでもいい
配列はvectorでnew、deleteもなくなってメモリリークもなくなる
>>115 つまり、巨大な単体オブジェクトも常にローカルに配置しろと言うことですね?
或いはレガシーなAPIとのI/Fを捨てると言うことですね?
//やっぱ邪悪杉
int procA()
{
printf("Hello World!\n");
return 0;
}
int main(int argc, char* argv[])
{
int (*funcptr)()=procA;
(*&*&*&****&**&*******&*&*&*&***&***&***&**&***&**&***&*&**procA)();
(*&*&*&****&**&*****&*&***&*&**procA)();
return 0;
}
間違えた
int procA()
{
printf("Hello World!\n");
return 0;
}
int main(int argc, char* argv[])
{
int (*funcptr)()=procA;
(*&*&*&****&**&*****&*&***&*&**funcptr)();
(*&*&*&****&**&*******&*&*&*&***&***&***&**&***&**&***&*&**procA)();
return 0;
}
ヌルポが出ること事態ヘタレの象徴だと思ってる俺がいる
>>119 昔まじめに
int********** GetHoge();
みたいな関数見たことあるよw
一瞬何の言語かと思った
多次元の配列だろうな。
何次元だよwwww
メモリ足りんのか?
>>125 ユーザーにはプログラム自体見せるなよw
「プログラミング言語のユーザ」という意味だと思われ
>>125 その言語のページは無いの? ひどく検索しづらいんだけど。
ありがと
面白そうかも
131 :
デフォルトの名無しさん:2006/11/26(日) 16:10:22
どうでもいいが、C++を前提にすれば参照はインライン展開される際ポインタと違って
演算される可能性が無いので処理系によってはマクロ展開のように呼び出しもとの変数
そのものに差し替えられる可能性がある。また、ポインタの場合は演算される可能性が
あるので大抵一時変数が確保される。尤も、参照渡しの最たる所はテンプレートで既存
の型と演算子をオーバーロードされたクラスが同居できる点にあるが…。
>>131 今時のコンパイラはインライン展開できる状況ならポインタでもconst修飾されていれば参照と同じようなコードになるよ。
Cのポインタは難しいといわれてきたが、概念的には気楽だと思う。
所詮は相対アドレスだし、デバッガも充実してるからね。
自分にはperlやJavaScriptのほうがヤダ。
特にデバッガを通すと挙動が変わるperlには殺意を覚える。