인덱스 접근 연산자 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() 메소드가 추가되었습니다.
장점:
단점: