ProgrammingC++ 開発者

C++におけるポインタと参照の動作原理を説明してください。それらはどのように異なり、いつ何を使うべきでしょうか?

Hintsage AIアシスタントで面接を突破

回答。

この問題の歴史:

ポインタはC++の主要なツールの1つであり、言語の登場以来、メモリ管理や動的データ構造の基盤として、また低レベルシステムライブラリとの相互作用のために使用されています。参照は後に追加され(C++の登場とともに)、構文を簡素化し、コードの安全性を高めるために導入されました。

問題:

メモリを扱う際のエラーはC++で最も一般的な問題の1つであり、特にポインタの誤った使用(ダングリングポインタ、メモリリーク)によって引き起こされます。初心者は、参照を使用すべき場合とポインタを使用すべき場合が分からなかったり、それらが完全に相互に置き換え可能であると誤解したりすることがあります。

解決策:

ポインタ(T*)は、オブジェクトのアドレスを保存する変数であり、nullptrになり得ます。算術演算をサポートし、動的なメモリの割り当てと解放を許可し、指し示す先を変更できます。

参照(T&)は、別の既存のオブジェクトのエイリアスです。参照は作成時に初期化される必要があり、「空」であること(nullを参照すること)はできず、算術演算をサポートしませんが、機能に渡す際などで便利で安全です。

コード例:

void increment_pointer(int* p) { if(p) ++(*p); } void increment_reference(int& r) { ++r; } int main() { int a = 5; increment_pointer(&a); increment_reference(a); }

主な特徴:

  • ポインタは再指向可能ですが、参照はできません
  • 参照は常に実際のオブジェクトに関連付けられている必要がありますが、ポインタはnullptrになることができます
  • 関数に渡す際には参照が好まれる場合が多く、参照が使用できない場合にポインタを使用します

トリッキーな質問。

初期化後に参照を変更して別のオブジェクトを参照させることはできますか?

できません。C++における参照は定数エイリアスです。一度初期化されると、参照は常に同じオブジェクトを指し続けますが、ポインタは再指向できます。

コード例:

int a = 1; int b = 2; int& ref = a; // ref = b - bの値を代入しますが、refは引き続きaを参照します

「ヌル」参照やnullptrを参照する参照を作成できますか?

できません。標準は存在しないオブジェクトを参照することを許可していません。これは未定義の動作を引き起こします。

例:

int* p = nullptr; // int& r = *p; - UB

int const ptr と const int ptr は何が違いますか?**

int* const ptrはintの定数ポインタ(ポインタを再指向できませんが、値は変更できます)。const int* ptrは定数intへのポインタ(指している内容を変更できませんが、ポインタを再指向できます)。

コード例:

int a = 1, b = 2; const int* ptr1 = &a; // *ptr1は変更できませんが、ptr1 = &bは可能 int* const ptr2 = &a; // *ptr2は変更可能ですが、ptr2 = &bはできません

型のエラーとアンチパターン

  • 一時的な値やすでに削除されたオブジェクトへの参照の使用
  • ポインタの再割り当て無しにメモリを再配置
  • 「ヌル」参照 - UB

実生活からの例

ネガティブケース

若い開発者がポインタを使用してパラメータを渡し、nullptrをチェックせずにエラー時にクラッシュしました。

プラス:

  • エラーが発生するまで動作した

マイナス:

  • 不正な呼び出しによる不明なクラッシュ
  • エラーの追跡が難しい

ポジティブケース

経験豊富な開発者が、渡すことが確実な場合にはint&を、nullptrの可能性がある場合にはint*を使用し、必ずポインタをnullでチェックしました。

プラス:

  • メモリエラーの最小化
  • 関数の明確なセマンティクス

マイナス:

  • 動的メモリを扱う際に時折複雑さを引き起こす