ポインタと参照
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 13/104。
スタックメモリとヒープメモリについて理解したところで、メモリ位置を直接操作するためのツールであるポインタと参照について見ていきましょう。
ポインタは、別の変数のメモリ番地を格納します。* を使って宣言し、& を使ってアドレスを取得します。
int value = 42;
int* ptr = &value; // ptrはvalueのアドレスを保持します
std::cout << ptr; // メモリアドレスを出力します
std::cout << *ptr; // デリファレンス:42を出力します参照は、既存の変数の別名です。一度バインドされると、常にその変数を指します。& を使って宣言します。
int value = 42;
int& ref = value; // ref は value の別名です
ref = 100; // value を 100 に変更します
std::cout << value; // 100 を出力します主な違い:
| ポインタ | 参照 |
|---|---|
| null になる可能性がある | 初期化が必要 |
| 再代入が可能 | 再バインド不可 |
値にアクセスするには * を使用する | 値に直接アクセスする |
| 何も指さないことが可能 | 常に有効 |
オブジェクトをコピーせずに効率的に関数に渡すため、またヒープ割り当てメモリを扱うために、どちらも不可欠です。参照はより安全でシンプルですが、ポインタは再代入やnullのチェックが必要な場合により高い柔軟性を提供します。
チャレンジ
簡単ポインタと参照がデータを変更する際にどのように異なって動作するかを実証する、シンプルな値操作システムを構築しましょう。
コードを整理するために、2つのファイルを作成します。
ValueOps.h: 整数値を異なる方法で変更する3つの関数を定義します。doubleByPointer(int* ptr)— ポインタを受け取り、それが指す値を2倍にします。tripleByReference(int& ref)— 参照を受け取り、その値を3倍にします。swapValues(int* a, int* b)— 2つのポインタを受け取り、それらが指す値を入れ替えます。
main.cpp: 入力から2つの整数を読み取り、ポインタと参照の両方を実証します。- 元の値を表示します:
"Original: <first> <second>" - 最初の値に対して
doubleByPointerを使用し、その後表示します:"After double: <first>" - 2番目の値に対して
tripleByReferenceを使用し、その後表示します:"After triple: <second>" swapValuesを使用して両方の値を入れ替え、その後表示します:"After swap: <first> <second>"
- 元の値を表示します:
ポインタを使用して関数を呼び出すときは、アドレス演算子 (&) を使用して変数のアドレスを渡すことを忘れないでください。参照はより自然に機能し、変数を直接渡すだけです。
main.cpp で #include "ValueOps.h" を使用してヘッダーファイルをインクルードしてください。
チートシート
ポインタは、別の変数のメモリ番地(アドレス)を格納します。* を使って宣言し、& を使ってアドレスを取得します。
int value = 42;
int* ptr = &value; // ptr は value のアドレスを保持します
std::cout << ptr; // メモリ番地を出力します
std::cout << *ptr; // デリファレンス:42 を出力します参照は、既存の変数の別名(エイリアス)です。& を使って宣言します。
int value = 42;
int& ref = value; // ref は value の別名です
ref = 100; // value を 100 に変更します
std::cout << value; // 100 を出力します主な違い:
| ポインタ | 参照 |
|---|---|
| null にできる | 初期化が必須 |
| 再代入ができる | 再バインドできない |
* を使って値にアクセスする | 直接値にアクセスする |
| 何も指さないことが可能 | 常に有効 |
ポインタを使って関数を呼び出すときは、アドレス演算子(&)を使用して変数のアドレスを渡します。参照の場合は直接動作するため、変数をそのまま渡すだけです。
自分で試してみよう
#include <iostream>
#include "ValueOps.h"
using namespace std;
int main() {
// 入力から2つの整数を読み取る
int first, second;
cin >> first;
cin >> second;
// 元の値を表示する
cout << "Original: " << first << " " << second << endl;
// TODO: first の値に対して doubleByPointer を使用する(& を使ってアドレスを渡す)
// TODO: 2倍にした後に表示する
// TODO: second の値に対して tripleByReference を使用する(変数を直接渡す)
// TODO: 3倍にした後に表示する
// TODO: swapValues を使用して両方の値を入れ替える(& を使ってアドレスを渡す)
// TODO: 入れ替え後に表示する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタ引数付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ詳解Rule of Three / Five / Zeroまとめ - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () 演算子のオーバーロード型変換演算子まとめ:Matrix クラス