El operador de acceso por índice operator[] es un operador sobrecargable en C++ que proporciona la sintaxis de indexación de objetos de contenedores personalizados (por ejemplo, como en arreglos).
Historia del tema:
En el lenguaje C, y más tarde en C++, el operador [] permitía acceder de manera rápida y conveniente a los elementos del arreglo por índice. Sin embargo, con el crecimiento de la popularidad de las clases de contenedores, surgió la necesidad de trasladar la misma sintaxis a tipos de datos personalizados.
Problema:
El diseño correcto de operadores de acceso por índice está relacionado con cuestiones de constancia, seguridad de acceso fuera de límites, elección de tipo de retorno y garantía de validez de la referencia o puntero.
Solución:
En C++, se puede sobrecargar operator[] para clases, permitiendo el acceso a los elementos por índice y realizando "comportamiento como un arreglo". Se deben implementar ambas versiones del operador: la normal (para objetos no constantes) y la constante (para objetos constantes).
Ejemplo de código:
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
Características clave:
.at() en contenedores estándar)¿Es obligatorio devolver una referencia desde operator[]?
No, pero si se devuelve un valor, la sintaxis arr[i] = x; no funcionará (estarás copiando en lugar de asignar). Para mantener la semántica habitual del contenedor, generalmente se devuelve una referencia. Si se devuelve un valor, no se podrá realizar una asignación al elemento:
int operator[](size_t idx); // arr[2] = 10; no se compilará
¿Debería operator[] verificar los límites?
El estándar no lo requiere. El operator[] clásico (como en std::vector) NO realiza tales verificaciones. Para las verificaciones, los contenedores estándar introducen un método separado .at(), que lanza una excepción al salir del rango de indexación.
¿Puede operator[] ser un método constante?
No, si devuelves una referencia no constante. Sin embargo, es necesario sobrecargar operator[] tanto para objetos constantes como no constantes, para que el contenedor funcione de manera intuitiva y segura.
Un joven desarrollador implementó solo la versión no constante de operator[], que devolvía por valor. Como resultado, no se podía acceder al contenedor a través de una referencia const, y cualquier intento de escritura funcionaba de manera extraña: los valores no se guardaban.
Pros:
Contras:
En el contenedor MyArray se implementaron ambas versiones de operator[], con un retorno correcto de referencias. Si es necesario, se agregó el método at() con verificación de límites.
Pros:
Contras: