インデックスアクセス演算子 operator[] は、ユーザー定義コンテナ(配列のような)オブジェクトのインデックス付け構文を提供するためにC++でオーバーロードできる演算子です。
歴史的背景:
C言語、そしてその後のC++において、演算子 [] は配列の要素にインデックスで迅速かつ簡便にアクセスできるようにしていました。しかし、コンテナクラスの人気が高まるにつれて、同じ構文をユーザー定義データ型に移行する必要が出てきました。
問題:
インデックスアクセス演算子の正しい設計は、定数性、範囲外アクセスの安全性(out-of-bounds)、返り値の選択、および参照またはポインタの有効性保証に関する問題を伴います。
解決策:
C++ではクラスのためにoperator[]をオーバーロードすることで、インデックスで要素にアクセスできるようにし、"配列のような動作"を実現できます。通常(非定数オブジェクト用)および定数(定数オブジェクト用)の両方のバージョンの演算子を実装する必要があります。
コードの例:
class MyArray { int data[10]; public: int& operator[](size_t index) { return data[index]; } const int& operator[](size_t index) const { return data[index]; } }; MyArray arr; arr[3] = 42; // OK const MyArray& const_arr = arr; int val = const_arr[3]; // OK
主な特徴:
.at()とは異なる)operator[]から参照を返すことは必須ですか?
いいえ — しかし、値を返すと、構文 arr[i] = x; は機能しません(代入ではなくコピーを行うことになります)。コンテナの慣習的な意味を保つために、通常は参照を返します。値を返すと、要素への書き込みができません:
int operator[](size_t idx); // arr[2] = 10; これはコンパイルできません
operator[]は範囲をチェックするべきですか?
標準では要求されていません。クラシックなoperator[](std::vectorのような)はそのようなチェックを行いません。標準コンテナは、範囲外アクセスの場合に例外をスローする別のメソッド.at()を導入しています。
operator[]は定数メソッドであるべきですか?
いいえ — もし非定数参照を返す場合は。しかし、operator[]は定数オブジェクトおよび非定数オブジェクトの両方に対してオーバーロードする必要があります。これにより、コンテナが直感的かつ安全に動作します。
若い開発者がoperator[]の非定数バージョンのみを実装し、値を返していました。その結果、コンテナにconst参照でアクセスできず、書き込みを試みると変な動作をする—値が保存されませんでした。
利点:
欠点:
コンテナMyArrayでは、両方のバージョンのoperator[]が実装されており、正しく参照が返されます。必要に応じて、範囲チェックのためのメソッドat()が追加されました。
利点:
欠点: