ポインタと参照の使い分け

ポインタと参照を、どう使い分けるのか分かりません、と質問されたことがあった。
C++言語において、いずれも他のオブジェクトを指し示すオブジェクトであって、性質が似ている。
似てるとはいえ違うわけで、そういうときは、その違いを比較して、使いどころを考える。


ポインタ参照
オブジェクトを指し示さない状態可能不可能
指し示す先の変更可能不可能


以上をもって、「参照に可能なことは、すべてポインタで可能なのだ」と判断するのは早計だろう。
自由度が高いということは、望まれないことも容易に可能であるということでもある。望まれないことをわざわざやる人もいないだろうが、容易に可能であるが故に、ケアレスミスによって発生しやすい。
上記比較を、以下のように言い換えてみる。


ポインタ参照
常に有効なオブジェクトを指し示す不可能可能
指し示す先の変更を禁止する不可能可能


参照側の「可能」という表現はいささか恣意的はあるが、というか「指し示す先の変更禁止」はconstを用いることによってポインタでも可能だが、最初の比較を言い換えただけなので、勘弁して欲しい。
ともあれ、「参照に可能なことは、すべてポインタで可能なのだ」とは言い切れないことは分かる。参照には、ポインタに実現不可能な性質があるのだ。


ポインタを使用する際には、それが有効なオブジェクトをポイントしていることを確認する必要がある。また、何もポイントしていないときは、ナル値を代入しておくなどの手作業によって、無効であることを示す必要がある。この無効を示す作業を怠ると、以降、そのポインタが使えるかどうか、判定する方法は無い。高い確率で、メモリリークや例外が発生するだろう。
参照は常に有効なオブジェクトを参照しているので、これらの危険は無い。
ところで、以下の場合はどうか。




int * p = 0;
int & r = * p;


この場合、例外が発生する。しかし、これはポインタが有効であることを確認する作業を怠ったためであって、参照の問題とはいえない。
「自由度が高い」とは「高機能」と等しいわけではなく、「自由度の制限」も、また「機能」といえる。必要以上の自由度は、害になりうる。
従って、何も指し示さない状態が不要のとき、かつ指し示す先を変更する必要が無いとき、参照を使うべきである。いずれかの必要がある場合は、注意深くポインタを使用する。




C++の設計と進化

C++の設計と進化

C++言語を設計したStroupstrup氏が『C++の設計と進化』において述べたように、C++言語は、C言語との互換性を重視し、ユーザーの自由を制限しないように設計された。従って、望ましくないことも容易に可能であり、その点はユーザーが意識して抑えられるようなコードを書かねばならない。
シートベルトが無くても車は走って曲がって止まるが、無くていい訳ではない。しかし、単一のシートベルト仕様が決まっていて、車の設計が制限されることはありえない。C++言語に過剰な安全機能が存在しないのは、そこはユーザーが自由にやることであるというポリシーからだろう。