[c++] STL 맵에 대해 [] 연산자가 const가 아닌 이유는 무엇입니까?

질문에 대한 설명 된 예 :

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map[x] << std::endl
}

[] 연산자가 상수가 아니기 때문에 컴파일되지 않습니다.

[] 구문이 매우 깔끔해 보이기 때문에 이것은 불행한 일입니다. 대신 다음과 같이해야합니다.

void MyClass::MyFunction( int x ) const
{
  MyMap iter = m_map.find(x);
  std::cout << iter->second << std::endl
}

이것은 항상 나를 괴롭 혔습니다. [] 연산자가 상수가 아닌 이유는 무엇입니까?



답변

들어 std::mapstd::unordered_map, operator[]이전에 존재하지 않은 경우 용기에 인덱스 값을 삽입합니다. 약간 직관적이지 않지만 그렇습니다.

실패하고 기본값을 삽입 할 수 있어야하므로 const컨테이너 의 인스턴스 에서 연산자를 사용할 수 없습니다 .

http://en.cppreference.com/w/cpp/container/map/operator_at


답변

이제 C ++ 11 에서는 at () 을 사용하여 더 깨끗한 버전을 가질 수 있습니다.

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map.at(x) << std::endl;
}


답변

새로운 독자를위한 참고 사항.
원래 질문은 STL 컨테이너에 관한 것이 었습니다 (특히 std :: map에 관한 것이 아님)

대부분의 컨테이너에는 [] 연산자의 const 버전이 있습니다.
std :: map 및 std :: set에는 const 버전이 없으며 이는이를 구현하는 기본 구조의 결과입니다.

std :: vector에서

reference       operator[](size_type n)
const_reference operator[](size_type n) const

또한 두 번째 예제의 경우 요소를 찾을 수 없는지 확인해야합니다.

void MyClass::MyFunction( int x ) const
{
    MyMap iter = m_map.find(x);
    if (iter != m_map.end())
    {
        std::cout << iter->second << std::endl
    }
}


답변

operator []는 컨테이너에 새 요소를 삽입 할 수 있으므로 const 멤버 함수가 될 수 없습니다. operator []의 정의는 매우 간단합니다. m [k]는 (* ((m.insert (value_type (k, data_type ()))). first)). second와 같습니다. 엄밀히 말하면이 멤버 함수는 불필요합니다. 편의를 위해서만 존재합니다.


답변

인덱스 연산자는 읽기 전용 컨테이너 (STL 자체에는 실제로 존재하지 않음)에 대해서만 const 여야합니다.

인덱스 연산자는 값을 보는 데만 사용되는 것이 아닙니다.


답변

std :: map 멤버 변수를 변경 가능하도록 선언하면

mutable std::map<...> m_map;

const 멤버 함수 내에서 std :: map의 상수가 아닌 멤버 함수를 사용할 수 있습니다.


답변