例えば、何も考えずに配列を引数で受け取る関数を考えるとします。
すると、以下のようになるかと思います。
#include <iostream>
void Func(const short array[4])
{
using namespace std;
for (int i = 0; i < 4; ++i) {
cout << array[i] << endl;
}
}
int main()
{
short array[4] = {
0, 1, 2, 3,
};
Func(array);
return 0;
}
ぱっと見、なんの問題もないように見えますが、実はこれ、 配列ではなく単なるポインタ扱い になっています。
どういうこっちゃ?どう見ても配列でしょ?と思うかもしれませんが、
以下のコードと実行結果を見れば一目瞭然です。
#include <iostream>
void Func(const short array[4])
{
using namespace std;
cout << sizeof(array) << endl;
}
int main()
{
using namespace std;
short array[4] = {};
cout << sizeof(array) << endl;
Func(array);
return 0;
}
8
4
関数外で sizeof すると、配列のサイズである 8 が出力されています。
が、関数内で sizeof するとあら不思議。出力されているのは 4 です。
この 4 はなんの 4 なのか?と言うと、これこそが short * のサイズである 4 となるわけです。
よって
void Func(const short array[4])
は
void Func(const short * array)
と同義というわけです。
まぁ、これでも 「short 型の要素数 4 の配列を渡してください」 という意図を伝えることはできますが、
残念ながら 「short 型の要素数 4 の配列を渡さなければならない」 ことにはできません。
あくまで short * なので、short * であれば、要素数が 10 でも 100 でも、
更には new したポインタ でさえ渡すことができちゃうわけです。
これをなんとか「short 型の要素数 4 の配列を渡さなければならない」ことにできないか?
これを実現できるのが 「配列の参照」 です。
百聞は一見にしかず。というわけで、コードと実行結果です。
#include <iostream>
void Func(short (&array)[4])
{
using namespace std;
cout << sizeof(array) << endl;
}
int main()
{
using namespace std;
short array[4] = {};
cout << sizeof(array) << endl;
Func(array);
return 0;
}
8
8
(&array)[4] が「配列の参照」となります。
() 重要です。ないとコンパイルエラーで怒られます。
実行結果を見ると、関数内、関数外の両方で 8 が出力されてますね。
8 が出力されているということは、「short 型の要素数 4 の配列」として認識されているということです。
という訳で、これで無事に「short 型の要素数 4 の配列を渡さなければならない」を実現することが出来ました。
ちなみに、きちんと配列として認識されていますので、
for (int i = 0; i < SIZEOF_ARRAY(array); ++i) {
cout << array[i] << endl;
}
こんなこともできます。