1. ホーム
  2. c++

[解決済み] リファレンスとポインタの使い分け

2022-03-22 06:23:16

質問

ポインタと参照の構文と一般的な意味合いは理解していますが、APIで参照とポインタのどちらを使うのが適切か、どのように判断したらよいでしょうか?

当然ながら、状況によってはどちらか一方が必要です ( operator++ しかし、一般的には、ポインタ(およびconstポインタ)を使用することを好むと思います。

例えば、以下のようなコードで。

void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
  int a = 0;
  add_one(a); // Not clear that a may be modified
  add_one(&a); // 'a' is clearly being passed destructively
}

ポインターを使えば、何が起こっているのかが常に(より)明らかなので、APIなどで分かりやすさが重視される場合には、リファレンスよりもポインターの方が適しているのではないでしょうか?つまり、リファレンスは必要なときだけ使うべきだということでしょうか(例. operator++ )? また、どちらか一方を選択することでパフォーマンス上の懸念はありますか?

を編集します(古っ)。

NULL値を許容することと、生の配列を扱うことの他に、個人的な好みによるということになるようです。私は、以下の回答を受け入れました。 GoogleのC++スタイルガイド 参照は値の構文とポインタのセマンティクスを持つため、混乱する可能性がある」という見解が示されているからです。

NULLであってはならないポインタの引数をサニタイズするために必要な追加作業のため(例えば add_one(0) はポインターのバージョンを呼び出し、実行時に壊れます)。オブジェクトが存在しなければならない場所では参照を使用することは保守性の観点から理にかなっていますが、構文の明快さを失うのは残念です。

どのように解決するの?

できる限り参照を使い、必要な場合はポインタを使う。

ポインターは避けるべき。

その理由は、ポインターは他のどのような構成よりも、物事を追いかけ/読みにくくし、安全性を低下させ、はるかに危険な操作になるからです。

ですから、ポインターは他に選択の余地がない場合にのみ使用するのが鉄則です。

例えば、オブジェクトへのポインタを返すことは、関数がそのオブジェクトへのポインタを返すことができる場合に有効な選択肢となります。 nullptr のように、場合によってはそうなることが想定されます。とはいえ、よりよい選択肢は、次のようなものを使うことでしょう。 std::optional (C++17が必要。それ以前は boost::optional ).

もう一つの例は、特定のメモリ操作のために生メモリへのポインタを使用することです。これは、コードベース全体の危険な部分を制限するのに役立つように、コードの非常に狭い部分に隠されて局所化されるべきです。

あなたの例では、ポインタを引数として使用する意味がありませんから。

  1. を指定した場合 nullptr を引数にとると、未定義ビヘイビアランドに突入してしまいます。
  2. の問題は、参照属性版では(簡単に見破れるようなトリックがなければ)許されない。
  3. 参照属性バージョンは、ユーザーにとってより理解しやすいものです:有効なオブジェクトを提供する必要があり、NULLの可能性があるものではありません。

もし関数の動作が与えられたオブジェクトの有無にかかわらず動作しなければならない場合、属性としてポインタを使用することで、そのオブジェクトに nullptr を引数にすれば、関数としては問題ない。これは、ユーザーと実装の間の契約みたいなものです。