C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のポインタ渡しと参照渡しの違いをサンプルコードで解説

C++では、関数に引数を渡す方法として「ポインタ渡し」と「参照渡し」の2つがよく使われます。どちらも呼び出し元の変数そのものを操作できるため、値渡しとは異なり、関数内での変更が呼び出し元にも反映されます。ここでは、2つの変数の値を入れ替えるswap関数を例に、それぞれの書き方と動作を見ていきましょう。

ポインタ渡し(pass by pointer)

ポインタ渡しでは、変数のアドレスを関数に渡します。関数側ではポインタを受け取り、間接演算子(*)を使ってアドレスが指す先の値にアクセスします。

#include <iostream>
using namespace std;

void swap(int* a, int* b) {
    int c = *a;   // aが指す値を一時変数cに保存
    *a = *b;      // bが指す値をaが指す場所へ代入
    *b = c;       // 保存しておいた値をbが指す場所へ代入
}

int main() {
    int m = 7, n = 6;
    cout << "Before Swap\n";
    cout << "m = " << m << " n = " << n << "\n";
    swap(&m, &n);   // 変数のアドレスを渡す
    cout << "After Swap by pass by pointer\n";
    cout << "m = " << m << " n = " << n << "\n";
}

実行結果

Before Swap
m = 7 n = 6
After Swap by pass by pointer
m = 6 n = 7

呼び出し側では &m のようにアドレス演算子を使って変数のアドレスを渡している点に注目してください。関数内では *a*b を通じて、元の変数 m と n の値を直接書き換えています。

参照渡し(pass by reference)

参照渡しでは、変数そのものへの別名(エイリアス)である「参照」を関数に渡します。呼び出し側は通常の変数を渡すだけでよく、関数内でも *& を意識せず、普通の変数のように扱えます。

#include <iostream>
using namespace std;

void swap(int& a, int& b) {
    int c = a;   // a(=mの別名)の値を保存
    a = b;       // b(=nの別名)の値をaへ代入
    b = c;       // 保存しておいた値をbへ代入
}

int main() {
    int m = 7, n = 6;
    cout << "Before Swap\n";
    cout << "m = " << m << " n = " << n << "\n";
    swap(m, n);   // 変数をそのまま渡す
    cout << "After Swap by pass by reference\n";
    cout << "m = " << m << " n = " << n << "\n";
}

実行結果

Before Swap
m = 7 n = 6
After Swap by pass by reference
m = 6 n = 7

実行結果からわかるように、ポインタ渡しでも参照渡しでも、同じように元の変数の値を入れ替えることができます。

ポインタ渡しと参照渡しの違い

両者は結果こそ同じですが、性質にはいくつかの重要な違いがあります。

  • 意味の違い: 参照は「既存の変数に付けた別名」であり、必ず実体のある変数を指します。一方、ポインタは「変数のアドレスを格納する変数」であり、アドレス自体を自由に扱えます。
  • NULLの扱い: 参照はNULLにならないため、原則として安全です。ポインタはNULLや無効なアドレスを持ちうるため、使う前に必ず有効性を確認する必要があります。
  • 再代入: 参照は一度初期化すると別の変数を指すように変更できません。ポインタは後から別のアドレスを代入できます。
  • 可読性: 参照渡しは呼び出し側のコードがシンプルになり、*& の記述が不要なため、読みやすくバグも起きにくくなります。
  • 柔軟性: 「対象がない可能性がある」ことを表現したい場合や、配列を扱う場合などは、ポインタの方が適しています。

まとめると、単純に関数内で呼び出し元の変数を書き換えたいだけであれば、NULLにならず記述も簡潔な参照渡しが推奨されます。ポインタ渡しは、NULL許容や動的なメモリ操作など、より低レベルな制御が必要な場面で活用するとよいでしょう。

  1. C++のポインタと参照の違いとは?初心者向けにわかりやすく解説

    C++には「参照(リファレンス)」と「ポインタ」という、どちらも間接的に変数を扱うための仕組みがあります。一見似ているこの2つですが、動作や使い方には重要な違いがあります。本記事では、それぞれの基本概念と構文を紹介したうえで、両者の主な相違点をわかりやすく解説します。 参照(Reference)とは 変数を参照として宣言すると、その参照は既に存在する変数の「別名(エイリアス)」として機能します。参照は元の変数と同じメモリ領域を共有するため、参照を通じて行った変更はすべて元の変数に直接反映されます。 構文 型 &新しい名前 = 既存の変数名; 初期化 int x = 10; int &a

  2. PHPの参照渡しとは?値渡しとの違いを実例付きで解説

    はじめに PHPでは、関数へ引数を渡す際に「値渡し」と「参照渡し」の2つの方法があります。デフォルトは値渡しで、実際の引数の値が仮引数にコピーされ、関数内ではローカル変数として扱われます。そのため、関数内で仮引数を変更しても、呼び出し元の変数の値は変わりません。 一方、参照渡しの場合、仮引数は呼び出し元の変数への参照となるため、関数内での変更がそのまま元の変数に反映されます。この仕組みにより、グローバルスコープのデータを間接的に操作できるほか、「関数から返せる値は1つだけ」という制約も回避できます。 値渡し(Pass by Value) 次の例では、2つの変数をswap()関数に渡しています