Const map element access
Solution 1
at()
is a new method for std::map
in C++11.
Rather than insert a new default constructed element as operator[]
does if an element with the given key does not exist, it throws a std::out_of_range
exception. (This is similar to the behaviour of at()
for deque
and vector
.)
Because of this behaviour it makes sense for there to be a const
overload of at()
, unlike operator[]
which always has the potential to change the map.
Solution 2
If an element doesn’t exist in a map
, the operator []
will add it – which obviously cannot work in a const
map so C++ does not define a const
version of the operator. This is a nice example of the compiler’s type checker preventing a potential runtime error.
In your case, you need to use find
instead which will only return an (iterator to the) element if it exists, it will never modify the map
. If an item doesn’t exist, it returns an iterator to the map’s end()
.
at
doesn’t exist and shouldn’t even compile. Perhaps this is a “compiler extension” (= a bug new in C++0x).
Solution 3
The []-operator will create a new entry in the map if the given key does not exists. It may thus change the map.
See this link.
Solution 4
This comes as quite a surprise to me, but the STL map doesn't have a const
index operator. That is, B[3]
cannot be read-only. From the manual:
I have no idea about at()
.
icephere
Updated on September 21, 2021Comments
-
icephere over 2 years
I tried to use the
operator[]
access the element in aconst map
, but this method failed. I also tried to useat()
to do the same thing. It worked this time. However, I could not find any reference about usingat()
to access element in aconst map
. Isat()
a newly added function inmap
? Where can I find more info about this? Thank you very much!An example could be the following:
#include <iostream> #include <map> using namespace std; int main() { map<int, char> A; A[1] = 'b'; A[3] = 'c'; const map<int, char> B = A; cout << B.at(3) << endl; // it works cout << B[3] << endl; // it does not work }
For using "B[3]", it returned the following errors during compiling:
t01.cpp:14: error: passing ‘const std::map<int, char, std::less, std::allocator<std::pair<const int, char> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = char, _Compare = std::less, _Alloc = std::allocator<std::pair<const int, char> >]’ discards qualifiers
The compiler used is g++ 4.2.1
-
Tim Martin about 13 yearsDoes the C++ standard forbid the implementation from defining additional non-standard member functions in library classes?
-
Konrad Rudolph about 13 years@Tim I believe the interface is fixed, yes.
-
user1202136 over 11 yearsIs is possible to have "at" return a default value instead of throwing an exception?
-
thomthom over 10 yearsI'm using
at()
with in VS2013 on a project set to use VS2010 toolkit. I thought that meant I wasn't using C++11... But yet it compiles... ?? -
Spencer about 6 yearsI just need to comment that it doesn't make sense to omit the const operator[], which could also throw an exception for an unmapped element instead of changing the map.
-
Brian Bi about 5 years@Spencer It would be surprising if the const and non-const overloads of operator[] had different effects. Normally, we expect that if some non-const objects or references in a program are made const, the program will continue to behave in the same way, as long as it compiles. Allowing only the non-const overload to throw exceptions can result in bugs that are not caught until runtime.
-
Spencer about 5 years@Brian Did you mean to say "Allowing only the const overload to throw exceptions"?
-
Brian Bi about 5 years@Spencer yes, sorry, that's what I meant.
-
Spencer about 5 years@Brian Thanks for clearing that up. Of course, I disagree with the reasoning in your original comment...it's possible that you consider something a bug that I'd consider expected behavior, and vice versa.
-
Brian Bi about 5 years@Spencer The "bug" in this case would be that after changing some non-const references to const references, the compiler would not warn you that some previously non-throwing operations have become potentially throwing. So then your program could crash in production because of the unhandled exception.
-
Spencer about 5 years@Brian Trading a silent, possibly corrupting error for a noisy one. That's a good thing.
-
Brian Bi about 5 years@Spencer no - in the status quo, there is no const overload of
operator[]
, so you get a guaranteed compile time error. If a const overload ofoperator[]
were introduced with behaviour similar toat
, then the guaranteed compile time error would turn into a runtime exception -
Spencer about 5 yearsLet us continue this discussion in chat.