Why isn't the [] operator const for STL maps?
Contrived example, for the sake of the question:
void MyClass::MyFunction( int x ) const
{
std::cout << m_map[x] << std::endl
}
This won't compile, since the [] operator is non-const.
This is unfortunate, since the [] syntax looks very clean. Instead, I have to do something like this:
void MyClass::MyFunction( int x ) const
{
MyMap iter = m_map.find(x);
std::cout << iter->second << std::endl
}
This has always bugged me. Why is the [] operator non-const?
Solution 1:
For std::map
and std::unordered_map
, operator[]
will insert the index value into the container if it didn't previously exist. It's a little unintuitive, but that's the way it is.
Since it must be allowed to fail and insert a default value, the operator can't be used on a const
instance of the container.
http://en.cppreference.com/w/cpp/container/map/operator_at
Solution 2:
Now that with C++11 you can have a cleaner version by using at()
void MyClass::MyFunction( int x ) const
{
std::cout << m_map.at(x) << std::endl;
}
Solution 3:
Note for new readers.
The original question was about STL containers (not specifically about the std::map)
It should be noted there is a const version of operator [] on most containers.
It is just that std::map and std::set do not have a const version and this is a result of the underlying structure that implements them.
From std::vector
reference operator[](size_type n)
const_reference operator[](size_type n) const
Also for your second example you should check for a failure to find the element.
void MyClass::MyFunction( int x ) const
{
MyMap iter = m_map.find(x);
if (iter != m_map.end())
{
std::cout << iter->second << std::endl
}
}
Solution 4:
Since operator[] might insert a new element into the container, it can't possibly be a const member function. Note that the definition of operator[] is extremely simple: m[k] is equivalent to (*((m.insert(value_type(k, data_type()))).first)).second. Strictly speaking, this member function is unnecessary: it exists only for convenience