【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&)を活用するとよいでしょう。
-
C/C++のmemcpy()関数の使い方と実例解説
この記事では、C++ STLにおけるmemcpy()関数の動作、構文、および具体的な使用例について詳しく解説します。 memcpy()とは? memcpy()関数は、C++ STLに組み込まれた標準関数の一つで、<cstring>ヘッダーファイルで定義されています。この関数はメモリブロックをコピーするために使用され、あるメモリ位置から別のメモリ位置へ、指定されたバイト数分のデータを転送します。 関数の実行結果は、データのバイナリコピーとなります。重要な点として、memcpy()は終端のNULL文字やその他の終端記号をチェックしません。単純にソースから指定されたバイト数(num)をそ
-
C/C++で学ぶAA木(AA Tree)とは?基本概念と平衡化操作を徹底解説
AA木(AA Tree)とはコンピュータサイエンスにおいて、AA木(AA Tree)とは、順序付きデータを効率的に格納・検索するために実装された平衡木(バランスドツリー)の一種です。AA木は、赤黒木(Red-Black Tree)の変種として扱われます。赤黒木は二分探索木の一形態であり、要素の追加や削除を効率的にサポートします。赤黒木と大きく異なる点は、AA木では赤いノードを右の子としてのみ追加でき、左の子としては配置できないという制約があることです。この制約により、2-3-4木ではなく2-3木をシミュレートすることになり、その結果、木の保守操作が大幅に簡素化されます。赤黒木の平衡化アルゴリズ