ページ 1 / 1
参照型の実体
Posted: 2009年10月18日(日) 21:31
by チルチル
今まで参照型と言う言葉すら知らなかったので参照は何をやっているのかの解釈は
宣言と同時にアドレスを書き換えるから作った方のアドレスは行方不明になるとか思っていましたが
調べて見るとそうではなくて参照型と言う型の存在を知りました
そこで気になったのが参照型で実体は作られるのかと言う事です
ポインタを宣言しても実体は作られませんが参照型も実体は作られないのでしょうか?
コンストラクタを非公開にしても参照型は作れるので実体は作られていないと思うのですが
試しにsizeof演算子でサイズを測ってみるとポインタは実体よりサイズが小さいのですが
参照型のサイズは実体と同じになるんですよね
まあ参照型も使う時は実体と同じですから同じに見えるのも頷けますが
では実際のサイズはどうなのでしょうか?
つまり参照型を作った時に増えるメモリ領域は実体を作った時より少ないのでしょうか?
関数の引数とかは参照の方が軽いと言われているから少ないと思いますが
それならポインタと参照型ではどっちが少ないのでしょうか?
Re:参照型の実体
Posted: 2009年10月18日(日) 21:55
by ねこ
ポインタ変数(ポインタクラス変数含む)ってのはアドレス持ってるだけだよ?
どっちが少ないとか言ってるってことはポインタが全然理解出来てないだけだと思う。
逆に言えばポインタより小さいサイズの参照方法なんて32ビットマシンでどうやってやるのさ、と。
これを読んで分からないなら、ポインタの概念をもう一回勉強した方がいい。
Re:参照型の実体
Posted: 2009年10月18日(日) 22:07
by conio
>>関数の引数とかは参照の方が軽いと言われているから少ないと思いますが
この発言から察するに、
「なんとなく」で解釈している部分があるのではないでしょうか。
根本的な所で、どういう事が行われているのか?などを正確に把握する必要があると思います。
で、関数の引数についてですが、
基本的に、リファレンス(参照)渡しの効率はアドレス渡しと同等です。
ただし、作業用無名インスタンスが生成されるような場合は、
リファレンス渡しは、遅くなります。
また、リファレンスやアドレス渡しの方が速いと判断しているようですが、
組み込み型(intなど)の引数であれば値渡しの方が効率が良いです。
Re:参照型の実体
Posted: 2009年10月18日(日) 23:58
by チルチル
参照型が内部で何をやっているか以外は理解していると思うんですけどね・・
参照型よりポインタ型の方が軽いとは思いましたけど確認のために聞きました・・
ちなみにどのくらい差がありますか?
参照渡しが速い理由はだいたい理解していますが「作業用無名インスタンス」とは何ですか?
それで気になっているsizeof(T)とsizeof(T&)ですが
これが同じ値になると言う事は
Tの参照型を作るとTを作るのと同じだけメモリが確保されると言う事でしょうか?
そうだとするとサイズの大きいユーザ定義型の参照型を多用すると
メモリを大量に消費してしまいますからこれははっきりさせる必要がありまして・・
Re:参照型の実体
Posted: 2009年10月19日(月) 00:36
by ねこ
何かやりたい事が分かった気がする。
違ってたら申し訳ないですが、チルチルさんはソースは短い方が良い主義みたいなので
NULLチェックをわざわざ書かなくても良いように参照型を使いたい
しかし、参照型はサイズ分メモリを確保してそうなのでそれは無駄と感じる。
こんなとこでしょうか?
もしそうなら答えは「増える」です。
メンバ関数の中で参照型変数作らなきゃいけないですからね。
同一階層で1万個とか作るならそりゃ大量に消費しますけどね、
ヒープ領域でちょこっと作る程度じゃ大差ないけど。
結局参照型に設定する際にNULLチェックは必要だし、別に絶対NULLが入らないって設計にすればNULLチェック無しで進めても良いと思うけどね。一般的ではないけど。
Re:参照型の実体
Posted: 2009年10月19日(月) 01:04
by conio
>>参照型よりポインタ型の方が軽いとは思いましたけど確認のために聞きました・・
>>ちなみにどのくらい差がありますか?
既に述べました。例外を除き、「同等」です。
(アドレス渡しも参照渡しも、同様の仕組みで実現しているからです。)
例外というのは、作業用無名インスタンスが作られる場合です。
で、作業用無名インスタンスについてですが、constリファレンスの場合は
オリジナル(参照する対象)と参照型指定に使われる変数が異なっていても良いという事になっています。
(ただし、変換可能な型である必要がある)
例えば、
---------------------
TempA a;
const TempB & b = a
---------------------
上記の様な場合、TempA型であるオリジナル(a)がTempB型に変換、コピーされ
その変換されたものは、TempB型の作業用インスタンスに代入されます。
そして、bはその生成されたTempB型のインスタンスのアドレスを格納する事になります。
つまり、直接 オリジナルであるaのアドレスを格納するわけでは無くなるので、
その作業の分だけ遅くなります。
(この場合のオーバーヘッドは、値渡しとアドレス渡しのオーバーヘッドを合計したものと同じ程度になります)
Re:参照型の実体
Posted: 2009年10月19日(月) 17:55
by チルチル
なるほど良くわかりました
参照型はサイズ分メモリを確保していると言うのは思い過ごしだったんですね・・
見かけ上はsizeof(T)とsizeof(T&)は同じになるけど
実際に確保されるメモリの量は「T*」も「T&」も同じになるんですね
まあconstは使わないから例外は考えなくて良さそうです
確認なんですが参照型もポインタ型も新たに確保される領域は同じだから
仮に物凄く大きい型の参照型を作ったからって物凄く大きい領域が確保されるわけでは無いんですよね?
Re:参照型の実体
Posted: 2009年10月20日(火) 00:54
by Ma
>確認なんですが参照型もポインタ型も新たに確保される領域は同じだから
>仮に物凄く大きい型の参照型を作ったからって物凄く大きい領域が確保されるわけでは無いんですよね?
特に詳しいわけではないですが、これまでの解答(以下の文)からそういうことになるかと。
>基本的に、リファレンス(参照)渡しの効率はアドレス渡しと同等です。
>>>参照型よりポインタ型の方が軽いとは思いましたけど確認のために聞きました・・
>>>ちなみにどのくらい差がありますか?
>既に述べました。例外を除き、「同等」です。
>(アドレス渡しも参照渡しも、同様の仕組みで実現しているからです。)
Re:参照型の実体
Posted: 2009年10月20日(火) 16:12
by チルチル
なるほど、やはり考えすぎでしたか
どうもありがとうございました