Root One

数学中心のブログです。

C++で関数に配列を渡す時の難点

配列利用時の不満点

C言語でも同じですが、C++でも配列を外部の関数に渡すと、外部の関数内で配列のサイズの取得ができなくなってしまいます。
そこで、配列を渡す時に、次のように一緒にサイズも渡さなければなりません。
渡された配列の要素に1を加えるだけの関数 addOne.

#include <iostream>
using namespace std;

void addOne(int* a, int size) {
	for (int i = 0; i < size; i++)
	{
		a[i]++;
	}
}
int main()
{
	int a[] = { 1,2,3 };
	int len = end(a) - begin(a);
	addOne(a, len);
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << endl;
	}
}

実行結果.

2
3
4

さらにC++の場合、配列のサイズ取得は、できたとしても上のように少し面倒です。sizeofを利用する方法もありますが、やはりそれも面倒です。
以上、2点が配列に関する利用者の不満点なのではないかと思います。

代替手段 (vectorの利用)

上記の不満は、vector を使えば解決します。

#include <iostream>
#include <vector>
using namespace std;

void addOne(vector<int>& v) {
	for (int i = 0; i < v.size(); i++)
	{
		v[i]++;
	}
}
int main()
{
	vector<int> v{ 1,2,3 };
	addOne(v);
	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << endl;
	}
}

実行結果.

2
3
4

vectorは要素数の取得も簡単で、しかも要素数変更までできるという優れものです。
これを利用しない手はないのですが、しかし、実行速度は状況によっては落ちてしまうかもしれません。
ということで、もう一つの代替手段を考えます。

代替手段 (array の利用)

array はおそらくvectorよりも高速に処理されるものと思われます。

#include <iostream>
#include <array>
using namespace std;

template <int N>
void addOne(array<int,N>& ar) {
	for (int i = 0; i < ar.size(); i++)
	{
		ar[i]++;
	}
}
int main()
{
	array<int,3> ar{ 1,2,3 };
	addOne(ar);
	for (int i = 0; i < ar.size(); i++)
	{
		cout << ar[i] << endl;
	}
}

実行結果.

2
3
4

素数の取得も簡単で、要素数を関数に渡す必要もありません。
ただし、非型テンプレートパラメータを使っています。

処理速度の比較

通常の配列、array, vectorで速度比較している方がすでにいらっしゃるようなので、
ここでは詳しく述べませんが、個人的に少し調べたところ、
debugモードで、
通常の配列 < array < vector
の順番で、結構明確な差が出ました。
一方releaseモードでは、
通常の配列とarray の速度差はわからないほどになりました。
実験に使ったコードでは、
0を初期値として持つ20万個の要素を定義して、関数内で+1するという
処理にかかる時間を計測しました。