#pragma twice

KAB-studio > プログラミング > #pragma twice > 065 Version 4.15 const 再び

#pragma twice 065 Version 4.15 const 再び

前のページへ 表紙・目次へ 次のページへ

 Version 4.15
const 再び

前回、ポインタの使用例でこういう関数を紹介しました

void RetTwoValueToPointer( int *p_piRet1, int *p_piRet2 )
{
    *p_piRet1 = 100;
    *p_piRet2 = 200;
}

値をふたつ返すためにポインタを使う、って例だよね
つまり、引数にポインタを使うメリットのひとつは、値を返すことができ
る、ってこと
ってことは、他にもメリットがあるんだ
そう。もうひとつのメリットは〈新たに作る変数はポインタ〉って点
どゆこと?
関数の引数は〈変数の一種〉だから、新しく作られます
かなり昔にそんなこと言ってたね
 Ver 2.10 ( No.021 )だね。で、まずポインタとか使わない場合。 int 
型の変数を作って、引数も int 、つまりポインタや参照じゃない場合
んっと、たとえば関数が F( int p_i ) みたいな感じで、それを F( i )
みたいに呼ぶってことよね
そうそう。この場合、元の変数と、引数の変数と、変数がふたつ作られる
ことになります
あー、そう考えるとなんか無駄って感じ
ま、こんくらいコンピューターには負担になんないけどね。ちなみにこう
いう〈ポインタや参照を使わずに渡す〉ことを〈値渡し〉って言います
ねわたし?
そ、値を直に渡すから。それに対して〈ポインタや参照を使って渡す〉こ
とを〈参照渡し〉っていいます
ポインタ渡しって言わないの?
話がこんがらがるけど、ポインタも、一般の意味での〈参照〉だから
あー、240ページ開いて、みたいな意味だよね。確かにアドレス値がそ
ういう役目だもんね
さて話を戻しましょう。ポインタを使って渡した場合
 F( int *p_i ) で F( &i ) みたいな感じだよね
この場合、元の変数と、引数のポインタ、変数がふたつ作られます
……おなじやん! ってツッコミ入れていいんだよね
そう。ポインタも変数の一種だからね。ところが、元の変数が〈クラス〉
の場合には話が違ってきます
お、懐かしい言葉! 変数に変数が入ってたり、関数付いてたりするのだ
よね
そうそう。クラスには〈メンバ変数〉っていう機能があって、中にいっぱ
い変数を入れることができます
詳しくは Ver 3.7 ( No.032 )だね。いっぱい変数が入ってるってことは、
メモリいっぱい食いそうだね
そうそう、 int は4バイトだったけど、クラスはその何倍にもなります。
さて、このクラス型変数が〈元の変数〉だった場合
値渡しの場合……他にクラスって知らないから CDialog で書くけど、
F( CDialog p_cDlg ) で、 F( cDlg ) って呼ぶ感じだよね
そう。この場合、元の CDialog と、引数の CDialog 、ふたつが作られた
わけ
対して参照渡しの場合…… F( CDialog *p_cDlg ) で、 F( &cDlg )  、
同じって気もするけど
そう? ポインタのサイズは?
 int と同じ4バイト。あ……ってことは、参照渡しだと、元の CDialog
と引数の CDialog のポインタを作るんだから
引数の方の変数のサイズについて見れば、参照渡しの方がサイズが小さく
なるわけ
値渡しだと CDialog でかなり大きい、参照渡しだとポインタだから4バ
イト。なるほど
その他にも参照渡しのメリットがあったり
あのさ、前回出てきたから見返したんだけど、Ver 3.22 ( No.047 )でやっ
た theApp って複製作れないでしょ、それって値渡しできないってことじゃ
ない?
そう! よく気が付きました。クラスは仕様によっては複製が作れない場
合があるから、そういう場合には参照渡しじゃなきゃダメ。よく気が付いた
ねー
うふふふふ
で、ここまでが前振り
なんの?
参照渡しのメリットは、値を返すだけじゃないよー、ってこと
なるほど。で、タイトルと合わせて鑑みると、それはつまり〈参照渡しで
値を変えられるのは危険!〉とかなって、 const 使うんでしょ
う”お、なんか先読みですね
ふふふ、今日はなんか冴えてるの
ではその通りというわけでこの関数

void ConstPointer( const int *p_piConst )
{
    TRACE( "%d\n", *p_piConst );  // 100
//  *p_piConst = 100;   // ビルドするとエラーになります。
}

// 下の関数を呼んでください。
void CallConstPointer()
{
    int i = 100;
    ConstPointer( &i );
}

えーっと? あ、まず引数が const int のポインタになってるね。こ
れって Ver 4.12 ( No.062 )で出てきたのだよね
そう、まったく同じもの。普通の変数を〈リードオンリーなポインタ〉に
したいときに const なポインタを作ります
あ、そうなると ConstPointer() の中から i に書き込みできないんだ
上のコメントアウト取り除いてビルドすると……

error C2166: 左辺値は const オブジェクトに指定されています。

これも同じエラーだね
こんなふうに、ポインタだけれども値を返さないようにすることができる
ってことだね
ってことはさ、参照も同じふうにできるの?
そう、できるんです

void ConstReference( const int &p_riConst )
{
    TRACE( "%d\n", p_riConst );   // 100
}

// 下の関数を呼んでください。
void CallConstReference()
{
    int i = 100;
    ConstReference( i );
}

あ、なんかほとんどポインタと同じだね
でしょう。ポインタとの違いは * が & になってるのと、 & と * がなく
なってるとこ
ふーん……
どしたの?
この前も思ったんだけど、 const 参照って、なんか違うかなーとか
ってゆーと?
もともと、ポインタってメモリとかアドレスとか、そういうのだったで
しょ。それが const 参照になっちゃうと、そういう自由度が全然ないって
ゆーか、なんかポインタと別もんってゆーか
そう、それが目的だからね
それが目的?
たとえば〈あるクラス型変数を、コピーを作らずに他の関数から操作した
い〉っていう場合
そーゆーときに const 参照を使うわけだよね
別に使わなくてもいいでしょ?
え?
本当にただのポインタでも、同じことはできるでしょ
確かにねー。 * とか付けて、書き込みに注意すればいいんだから
昔の C 言語っていうのは、そういうものだったの
むかし?
そう、参照なんてない時代。ポインタっていう道具を駆使していろんなこ
とをしてたわけ
その分面倒だったんだよね
それに危険だった。 int &ri で ri[3] ってしたらどうなると思う?
 ri って参照だよね。ってことは……

void ReferenceAndBrackets()
{
    int i = 100;
    int &ri = i;
    ri[3];  // ビルドエラー。
}

あ、エラー

error C2109: 配列または、ポインタでない変数に添字が使われました。

あ、ってことは参照って隣とか見れないんだ
そう。 * も使えないし、アドレスの足し算しようとしても
それって i の足し算とかになっちゃうよね。つまり参照だとアドレス操
作が全然できないんだ!
そういうこと。その分ポインタが持ってる危険度が少ないわけ
同じ参照渡しでも、ポインタより参照の方が安全ってことね。でもさ、元
はポインタなんでしょ?
そう、参照も、 const 参照も、 const ポインタも、基本的には普通のポ
インタ。それに制限が加えられたものってこと
確かに安全になるのはいいんだけど、ポインタの頃と、なんか感じが違う
かなーって
そうだね、参照とかって〈機能寄り〉かな
そういえば言ってたよね、必要な機能が先にあって、そのために道具が用
意されるんだって
元々はただのポインタだけだったんだけど、参照や const が必要になっ
たからどんどん付け加えられていったってこと
そうなっちゃうと、ポインタの面影がないよね
それはそうだよ。目覚まし時計使う時に、時計の中身のこと考える?
考えない。つまり時計そのものが参照で、中身はポインタ、ってこと?
何かの機能を使いたいときに、その仕組みは必要ないでしょ
でも……
火美ちゃんの気持ちは僕も分かるよ。あるひとつの道具を使いこなせると、
他の道具は要らないって思うもんだから
プ○ゴルファー猿みたいに?
ま、まぁ……
でもやっぱ、ゴルフにはアイアンとか必要だもんね
そう、場合によって道具を変えることが大事。火美ちゃん、僕が〈プログ
ラマーは自動車整備士なんだよ〉って言ったの憶えてる?
うん、憶えてる。 Ver 4.08 ( No.058 )で言ってたよね
火美ちゃんは今、自動車整備士の側になりすぎてるってこと。火美ちゃん
は〈ポインタ〉っていう中身の部分を急に知ったから、その視点にこだわっ
ちゃうんだよね
あ、つまり、車を乗る側に戻ってみればいいんだ!
そういうこと! 今火美ちゃんは〈変数の複製を作らずに関数に渡したい〉
と純粋に思った。なら?
参照を使うと便利! だよね?
これは何を作ることにも言えることだけど、クリエイターとユーザー、両
方の視点が大事
自分でクラブ作ってもそれに頼り切っちゃダメ、そのクラブが使えるかっ
て視点も大切、ってことね
なんかそれにこだわるね……

/*
    Preview Next Story!
*/
なんかすごい哲学的……
そんな感傷に浸ってる暇はありません
ホントに押せ押せだもんね
う”、ポインタ編も伸びちゃったしなー
というわけで次回
< Version 5.01 普通のアプリを作ろう >
につづく!
なんか変なタイトル……
新章はふたたびちゃんとしたアプリを作ります!
なんかすごいいきおい……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。