Operator dostępu przez indeks operator[] to operator przefinowywany w C++ do zapewnienia składni indeksowania obiektów użytkowych kontenerów (np. jak tablice).
Historia pytania:
W języku C, a później w C++, operator [] umożliwiał szybko i wygodnie odnosić się do elementów tablicy za pomocą indeksu. Jednak wraz ze wzrostem popularności klas kontenerowych pojawił się problem przeniesienia tej samej składni na użytkowe typy danych.
Problem:
Prawidłowe projektowanie operatorów dostępu przez indeks wiąże się z kwestiami stałości, bezpieczeństwa przed przekroczeniem zakresu (out-of-bounds), wyboru zwracanego typu oraz gwarancji ważności referencji lub wskaźnika.
Rozwiązanie:
W C++ można przeciążać operator[] dla klas, aby umożliwić dostęp do elementów przez indeks i zaimplementować dla nich "zachowanie jak w tablicy". Należy zaimplementować obie wersje operatora — zwykłą (dla obiektów nieconst) oraz konstantową (dla obiektów const).
Przykład kodu:
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
Kluczowe cechy:
.at() w standardowych kontenerach)Czy zwrot referencji z operator[] jest obowiązkowy?
Nie — ale jeśli zwracasz wartość, składnia arr[i] = x; nie zadziała (będziesz kopiować zamiast przypisywać). Aby wspierać przyjętą semantykę kontenera, zazwyczaj zwraca się referencję. Jeśli zwracasz wartość, to przypisanie do elementu nie zadziała:
int operator[](size_t idx); // arr[2] = 10; nie skompiluje się
Czy operator[] powinien sprawdzać granice?
Standard tego nie wymaga. Klasyczny operator[] (jak w std::vector) NIE wykonuje takich sprawdzeń. Dla sprawdzeń standardowe kontenery wprowadzają oddzielną metodę .at(), która rzuca wyjątek przy wyjściu poza zakres indeksowania.
Czy operator[] może być metodą konstantową?
Nie — jeśli zwracasz niekonstantną referencję. Jednak należy przeciążać operator[] zarówno dla obiektów konstantowych, jak i niekonstantowych, aby kontener działał intuicyjnie i bezpiecznie.
Młody programista zaimplementował tylko niekonstantową wersję operator[], zwracającą po wartości. W efekcie do kontenera nie można było odnosić się przez const-referencję, a wszelkie próby zapisu działały dziwnie — wartości nie były zapisywane.
Zalety:
Wady:
W kontenerze MyArray zaimplementowano obie wersje operator[], z poprawnym zwrotem referencji. W razie potrzeby dodano metodę at() z sprawdzeniem granic.
Zalety:
Wady: