프로그래밍C++ 중급 개발자

C++에서 operator[]란 무엇인가요? 사용자 정의 컨테이너에 대해 이 연산자를 올바르게 오버로드하는 방법은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

인덱스 접근 연산자 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

주요 특징:

  • 항상 const와 비-const 버전을 모두 구현하여 상수 객체와의 올바른 작업을 보장하세요.
  • 범위 초과 검사를 수행하지 않습니다 (표준 컨테이너의 .at()과는 대조적).
  • 반환 타입 (참조, 포인터, 값)을 신중하게 선택하는 것이 중요합니다.

함정 질문.

operator[]에서 참조를 반환해야 하나요?

아니요 — 그러나 값을 반환할 경우 arr[i] = x; 구문이 작동하지 않습니다 (값을 복사하게 됩니다). 컨테이너의 익숙한 의미론을 유지하기 위해 일반적으로 참조를 반환합니다. 값을 반환하면 요소에 기록할 수 없습니다:

int operator[](size_t idx); // arr[2] = 10; 구문 오류 발생

operator[]가 경계를 검사해야 하나요?

표준에서는 이를 요구하지 않습니다. 전통적인 operator[] (예: std::vector)는 그러한 검사를 수행하지 않습니다. 범위 초과 검사를 위한 별도의 메소드인 .at()이 표준 컨테이너에 도입되어 있습니다.

operator[]는 상수 메소드가 될 수 있나요?

아니요 — 비상수 참조를 반환하는 경우. 그러나 컨테이너가 직관적이고 안전하게 작동할 수 있도록 operator[]는 상수 및 비상수 객체 모두에 대해 오버로드해야 합니다.

전형적인 오류 및 안티 패턴

  • 상수 버전을 구현하지 않음 (따라서 const 참조로 요소에 접근할 수 없음)
  • 값을 반환하고 참조를 반환하지 않음으로써 할당 의미론이 깨짐
  • 컨테이너의 미초기화된 요소를 남김

실제 사례

부정적 사례

젊은 개발자가 값으로 반환하는 비상수 operator[] 버전만 구현했습니다. 결과적으로 컨테이너에 const 참조로 접근할 수 없었고, 모든 기록 시도는 이상하게 작동했습니다 — 값이 저장되지 않았습니다.

장점:

  • 비상수 객체만 사용할 때 컴파일됩니다.

단점:

  • 예상되는 C++ 의미론이 위배되었습니다.
  • const-correctness가 작동하지 않으며 표준 알고리즘이 지원되지 않습니다.

긍정적 사례

MyArray 컨테이너에서는 두 가지 버전의 operator[]가 모두 올바른 참조 반환으로 구현되었습니다. 필요에 따라 경계 검사 기능이 있는 at() 메소드가 추가되었습니다.

장점:

  • 컨테이너가 "표준에 따라" 작동합니다.
  • 모든 모드 (상수, 비상수, 읽기, 쓰기)를 지원합니다.

단점:

  • operator[]를 사용할 때 여전히 범위 초과 오류가 발생할 수 있습니다.
  • 클래스의 복잡성이 약간 증가합니다.