Why isn't the [] operator const for STL maps?
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
Why does const does not works with size() for stl map, whereas it works perfectly for other containers ?
You are not calling size()
on the map
. You are calling operator[]
on the map
, which is a non-const
operation, since it will create an element at that position if one does not already exist.
You then attempt to call size()
on the vector<string>
at that position, but it is too late by this point. Incidentally, size()
is const
on Standard Library containers.
can't I use map [ ] operator with const function keyword?
The reason is because operator[] isn't const? I know that a const function can call only other const function.
Yes; operator[]
is specified to create a new default-constructed element if the key doesn't exist, and this wouldn't be sensible on a const
map, thus it's not marked as const
.
Of course you could specify the const
version to throw an exception (as at
does) or - I don't know - call terminate
if the key isn't found, but alas the standard doesn't say that. You'll either have to use at
or (ugh) find
.
Why does std::map not have a const accessor?
operator[]
in a map returns the value at the specified key or creates a new value-initialized element for that key if it's not already present, so it would be impossible.
If operator[]
would have a const
overload, adding the element wouldn't work.
That answers the question. Alternatives:
For C++03 - you can use iterators (these are const
and non-const
coupled with find
). In C++11 you can use the at
method.
Why does the following not work when the map is const static
Using operator[]
on a std::map
creates the object if it doesn't exist. So it's an operation that can only be performed on a map you are allowed to modify. Use find instead.
Would really like to wrap my head around a 'const' issue with maps
If you look at the declaration for map's operator[], you will see that it is not const
qualified, which is why it cannot be called on a const std::map<std::string, double>
. The reason it is not const is because if the key does not exist in the map, it creates it. You should instead use find
or at
to get the element.
Why I can't use the std::map[ ] to add a string, but std::map.at() works?
std::map::operator[]
only works for a non-const
std::map
. The documentation on std::map::operator[]
explains this pretty well. Here's an excerpt from the beginning of the page:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
As you can see, if the key doesn't exist, it inserts a new key/value pair into the map. Obviously, this wouldn't work for const
maps because you can't insert elements into them since they're immutable. Why there isn't a const
overload for the operator that will not create a new value, I don't know. But that's just how it is.
std::map::at()
, however doesn't work exactly like std::map::operator[]
. Again, an excerpt from the documentation of std::map::at()
:
Returns a reference to the mapped value of the element with key equivalent to key. If no such element exists, an exception of type
std::out_of_range
is thrown.
Furthermore, the function has a const
overload too: const T& at(const Key& key) const;
So it can work for const
maps.
In addition, why both operator[] and .at() work for std::vector?
Because std::vector::operator[]
and std::vector::at()
work very similarly, except std::vector::at()
does bounds checking while std::vector::operator[]
doesn't. Neither will create a new value (because that's just not how vectors work) and both have const
overloads. In fact, the documentation for std::vector::operator[]
even addresses the difference between it and std::map::operator[]
:
Unlike
std::map::operator[]
, this operator never inserts a new element into the container. Accessing a nonexistent element through this operator is undefined behavior.
(It's undefined behavior because, as I previously mentioned, operator[]
does no bounds checking.)
Idiomatic C++ for reading from a const map
template <typename K, typename V>
V get(std::map<K, V> const& map, K const& key)
{
std::map<K, V>::const_iterator iter(map.find(key));
return iter != map.end() ? iter->second : V();
}
Improved implementation based on comments:
template <typename T>
typename T::mapped_type get(T const& map, typename T::key_type const& key)
{
typename T::const_iterator iter(map.find(key));
return iter != map.end() ? iter->second : typename T::mapped_type();
}
c++ Map [] operator not found
You're using the overridden operator[]
, which must have non-const access to the underlying map, as it will add a new entry if one doesn't exist at the requested key location. In your case that will add a NULL pointer (not going into the reasons for why).Your member function is declared as const
, and therefore the map is not modifiable.
Either declare the map as mutable
(NOT recommended), or use an iterator-search and return NULL if the search returned keywordItems.end()
. Otherwise, return the iterator's object (in it->second
).
Example
const ItemSet* Library::itemsForKeyword(const string& keyword) const
{
std::map<std::string, ItemSet*>::const_iterator it = keywordItems.find(keyword);
if (it != keywordItems.cend())
return it->second;
return nullptr;
}
Note: I would strongly advise using either direct objects, or at least smart pointers (such as std::shared_ptr<ItemSet>
) for your map object content. RAII: Its whats for dinner.
Related Topics
C++11: How to Alias a Function
What Is the Best Encryption Library in C/C++
How to Separate C++ Main Function and Classes from Objective-C And/Or C Routines at Compile and Link
How to Know If a Pointer Points to the Heap or the Stack
Allocating More Memory Than There Exists Using Malloc
Why Does Cudamalloc() Use Pointer to Pointer
What's Faster, Iterating an Stl Vector with Vector::Iterator or with At()
Case Insensitive Std::String.Find()
C++ Convert Vector<Int> to Vector<Double>
Qt Signals (Queuedconnection and Directconnection)
How Does C++ Stl Unordered_Map Resolve Collisions
Random Array Generation with No Duplicates
"The System Cannot Find the File Specified" When Running C++ Program
Is It a Good Idea to Return " Const Char * " from a Function
When Would Anyone Use a Union? Is It a Remnant from the C-Only Days
Gcc/G++: "No Such File or Directory"
Std::Set with User Defined Type, How to Ensure No Duplicates