配列のポインタ渡しと参照渡しの違い
ポインタ渡しとは以下のような処理です。
#include <iostream> using std::cout; using std::endl; // ポインタ渡し void func(int *a) { cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; func(a); }
また、以下のようにも書くことができます。
void func(int a[]) { cout << a[0] << endl; }
関数の仮引数におけるint a[]はint *aのシンタックスシュガーなのでまったくの同義なのです。
またこのとき要素数の指定も出来ますが、*aのシンタックスシュガーなので無視されます。
#include <iostream> using std::cout; using std::endl; // int *aのシンタックスシュガー void func(int a[10000]) { cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; func(a); }
上記処理はコンパイルエラーになりません。
さてお次は参照渡しの場合です。
#include <iostream> using std::cout; using std::endl; // 参照渡し void func(int (&a)[4]) { cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; func(a); }
参照渡しの場合は要素数の指定まで正確にしないとコンパイルエラーになります。
// 要素数10000にしてみる void func(int (&a)[10000] { cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; func(a); }
$ cl /W4 /EHsc main.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp main.cpp(12) : error C2664: 'func' : 1 番目の引数を 'int [4]' から 'int (&)[10000]' に変換できません。(新しい機能 ; ヘルプを参照)
となります。
また参照渡しの場合にした場合、ポインタ配列を渡すことができなくなります。
void func(int (&a)[4]) { cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; int *b = a; func(b); }
$ cl /W4 /EHsc main.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp main.cpp(12) : error C2664: 'func' : 1 番目の引数を 'int *' から 'int (&)[4]' に変換できません。(新しい機能 ; ヘルプを参照)
またあくまでも参照なので当然のごとくポインタの演算も出来ません。
void func(int (&a)[4]) { a++; // ポインタ演算 cout << a[0] << endl; } int main () { int a[] = {3,4,5,6}; func(a); }
$ cl /W4 /EHsc main.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp main.cpp(5) : error C2105: '++' には左辺値が必要です。