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

【C/C++入門】値渡し・アドレス渡し・参照渡しの違いを徹底解説

C言語では、関数へパラメータ(引数)を渡す方法として「値渡し(call by value)」と「アドレス渡し(call by address)」の2種類があります。さらにC++では、3つ目の手法である「参照渡し(call by reference)」が利用可能です。

この記事では、それぞれの仕組みと動作の違いを、実際のコード例と実行結果をもとにわかりやすく解説します。

1. 値渡し(Call by Value)

値渡しでは、呼び出し元の変数のコピーが関数の仮引数に渡されます。そのため、関数内でどれだけ値を変更しても、元の変数には一切影響しません。

コード例

#include <iostream>
using namespace std;
void my_swap(int x, int y) {
   int temp;
   temp = x;
   x = y;
   y = temp;
}
int main() {
   int a, b;
   a = 10;
   b = 40;
   cout << "(a,b) = (" << a << ", " << b << ")\n";
   my_swap(a, b);
   cout << "(a,b) = (" << a << ", " << b << ")\n";
}

実行結果

(a,b) = (10, 40)
(a,b) = (10, 40)

この例では、swap関数内でxとyの値は入れ替わっていますが、それはあくまでコピーされた値です。そのため、main関数側のaとbは元のまま変化していません。

2. アドレス渡し(Call by Address)

アドレス渡しでは、変数そのものではなく、変数のメモリアドレス(ポインタ)を関数に渡します。関数内でポインタが指す先の値を更新すると、呼び出し元の実際の変数も書き換えられます。

コード例

#include <iostream>
using namespace std;
void my_swap(int *x, int *y) {
   int temp;
   temp = *x;
   *x = *y;
   *y = temp;
}
int main() {
   int a, b;
   a = 10;
   b = 40;
   cout << "(a,b) = (" << a << ", " << b << ")\n";
   my_swap(&a, &b);
   cout << "(a,b) = (" << a << ", " << b << ")\n";
}

実行結果

(a,b) = (10, 40)
(a,b) = (40, 10)

呼び出し時に &a&b でアドレスを渡している点に注目してください。関数内では間接演算子 * を使ってアドレスが指す実体にアクセスするため、今度はaとbの値が正しく入れ替わっています。

3. 参照渡し(Call by Reference)※C++限定

参照渡しはC++で新たに導入された機能です。引数として参照変数を受け取るため、関数内での変更がそのまま呼び出し元の実体に反映されます。

記述方法は非常にシンプルで、関数定義時の仮引数名の前に & を付けるだけです。呼び出し側は通常の値渡しと同じ書き方で済むため、ポインタ構文よりも直感的で安全です。

コード例

#include <iostream>
using namespace std;
void my_swap(int &x, int &y) {
   int temp;
   temp = x;
   x = y;
   y = temp;
}
int main() {
   int a, b;
   a = 10;
   b = 40;
   cout << "(a,b) = (" << a << ", " << b << ")\n";
   my_swap(a, b);
   cout << "(a,b) = (" << a << ", " << b << ")\n";
}

実行結果

(a,b) = (10, 40)
(a,b) = (40, 10)

アドレス渡しと同様に、aとbの値が入れ替わっていることが確認できます。呼び出し側のコードが値渡しとまったく同じなのに、関数内の変更が反映されるのが参照渡しの大きな特徴です。

まとめ:3つの受け渡し方法の比較

方式渡すもの元の値への影響主な用途
値渡し値のコピー影響なし読み取り専用のデータ処理
アドレス渡しポインタ(アドレス)変更が反映されるC言語での関数外への書き込み
参照渡し参照(エイリアス)変更が反映されるC++での効率的かつ安全な引数受け渡し

単に関数内から値を書き換えたいだけであれば、C++では可読性の高い参照渡しを使うのが一般的です。一方、NULLチェックが必要な場面やC言語との互換性を保ちたい場合はアドレス渡しが適しています。また、意図しない変更を防ぎたい場合は値渡し、またはC++では const 参照(const int&)を活用するとよいでしょう。

  1. C/C++のmemcpy()関数の使い方と実例解説

    この記事では、C++ STLにおけるmemcpy()関数の動作、構文、および具体的な使用例について詳しく解説します。 memcpy()とは? memcpy()関数は、C++ STLに組み込まれた標準関数の一つで、<cstring>ヘッダーファイルで定義されています。この関数はメモリブロックをコピーするために使用され、あるメモリ位置から別のメモリ位置へ、指定されたバイト数分のデータを転送します。 関数の実行結果は、データのバイナリコピーとなります。重要な点として、memcpy()は終端のNULL文字やその他の終端記号をチェックしません。単純にソースから指定されたバイト数(num)をそ

  2. C/C++で学ぶAA木(AA Tree)とは?基本概念と平衡化操作を徹底解説

    AA木(AA Tree)とはコンピュータサイエンスにおいて、AA木(AA Tree)とは、順序付きデータを効率的に格納・検索するために実装された平衡木(バランスドツリー)の一種です。AA木は、赤黒木(Red-Black Tree)の変種として扱われます。赤黒木は二分探索木の一形態であり、要素の追加や削除を効率的にサポートします。赤黒木と大きく異なる点は、AA木では赤いノードを右の子としてのみ追加でき、左の子としては配置できないという制約があることです。この制約により、2-3-4木ではなく2-3木をシミュレートすることになり、その結果、木の保守操作が大幅に簡素化されます。赤黒木の平衡化アルゴリズ