blog.dopana

Back

C++入門シリーズの第5回です。変数はメモリ内のアドレスに存在します。ポインタと参照は、変数を間接的に参照する2つの方法で、どちらもC++では不可欠です。

変数のアドレス#

すべての変数はメモリアドレスに存在します。&で取得します:

int a = 42;
std::cout << &a << '\n';   // 例: 0x7ffee2b3d5ac
cpp

ポインタ#

ポインタはアドレスを格納します。何を指すかを表す型があります:

int a = 42;
int* p = &a;    // pはaを指す
cpp

*でデリファレンスして読み書きします:

std::cout << *p << '\n';   // 42
*p = 100;                  // aを変更
std::cout << a << '\n';    // 100
cpp

ヌルポインタ#

ポインタはアドレスを持たないこともできます。キーワードnullptrを使い、デリファレンス前に必ずチェックします:

int* p = nullptr;

if (p != nullptr) {
    std::cout << *p << '\n';
}
cpp

nullptrのデリファレンスはクラッシュです — ヌルポインタ参照。

参照#

参照は既存の変数のエイリアスです。一度バインドされ、再バインドできません:

int a = 42;
int& r = a;     // rはaの別名
r = 100;        // aを変更
std::cout << a << '\n';   // 100
cpp

参照はnullにはならず、後から別の変数を指すこともできません。

関数への渡し方#

参照渡しで、コピーなしに呼び出し元の変数を変更します:

void increment(int& x) {
    ++x;
}

int main() {
    int a = 5;
    increment(a);
    std::cout << a << '\n';  // 6
}
cpp

コピーを避けたいが変更はしない場合はconst int&を使います:

void describe(const std::string& s) {
    std::cout << s.size() << '\n';
}
cpp

ポインタと参照の比較#

ポインタ参照
nullにできる可(nullptr不可
対象を変更できる不可
デリファレンスが必要可(*暗黙
再代入p = &other不可

現代のC++では、関数パラメータには参照を優先します。nullや再バインドが必要な場合はポインタを使います。

結論#

ポインタも参照も変数に間接的にアクセスします。安全性には参照を優先し、nullや再バインドが必要ならポインタを使います。シリーズ次回はクラスとオブジェクトです。

参考文献#