Array クラスを作る (要素参照演算子編)

C/C++ では、配列の要素を参照するのに [] 演算子を用います。
Array クラスのオブジェクトに対しても、これと同様の方法で要素を参照できるように演算子オーバーロードしましょう。

Code 4-1: 要素参照演算子の実装
//要素参照
template <typename T> T& Array<T>::operator [] (int nIndex){
assert(0 <= nIndex && nIndex < m_nSize);
return m_lpa[nIndex];
}
//要素参照 (const)
template <typename T> const T& Array<T>::operator [] (int nIndex) const {
assert(0 <= nIndex && nIndex < m_nSize);
return m_lpa[nIndex];
}

非常に短く単純なコードですが、いくつか注意すべきポイントがあります。

1. 非const および const 演算子への対応

要素参照演算子は、非const オブジェクト用と、constオブジェクト用の2種類が必要です。
前者は、const 修飾のない要素への参照を戻り値とするので、これを利用して要素の値を変更することが可能です。

Code 4-2: non-const な要素アクセスの例
Array<char> an(100);
int i;
for (i=0; i<an.size; ++i){
an[i] =0; //non-const な要素参照
}

一方、const な要素参照は値の変更が不可能な Array オブジェクトに適用され、要素への読取専用アクセスを提供します。

Code 4-3: const な要素アクセスの例
//要素値の合計を計算
int Sum(const Array<int>& an){
int nSum =0;
int i;
for (i=0; i<an.size; ++i){
nSum +=an[i]; //const な要素参照
}
return nSum;
}

2. インデクス値の範囲チェック

インデクス値 (引数 nIndex) が有効な範囲内にあるかどうかのチェックは、assert を用いてチェックしています。
assert によるチェックはデバッグコンパイルでしか行われないため、if, throw を用いる方法に比べて、精度は下がりますが、リリース時のパフォーマンスに影響がしないという利点があるためこちらを採用しました