constant versus mutable iterator types

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

I am reading David Musser's "STL Tutorial and Reference Guide" Second
Edition.
In that book, on pages 68-69, definition has been given that "an
iterator can be mutable or constant depending on whether the result of
operator* is a reference or a constant reference."

As per this definition, on page 71 in this book, it is mentioned that
for 'set' and 'multiset', both the iterator and const_iterator types
are constant bidirectional types - in fact they are the same type.

The reason given in this book is as follows:

set<int> s;
s.insert(3);
s.insert(5);
s.insert(7);
set<int>::iterator i = s.begin();
*i = 4; // incorrect

On page 72, it is given that for container set<T>, set<T>::iterator is
constant bidirectional iterator category and for container
multiset<T>, multiset<T>::iterator is constant bidirectional iterator
category.

My understanding:
Along the same above discussion, shouldn't map<Key, T>::iterator and
multimap<Key, T>::iterator also be constant bidirectional iterators ?
(This is what I expected because for both set, multiset, map,
multimap, the key is constant)

However in this book, it is mentioned that for container map<Key, T>,
map<Key, T>::iterator is mutable bidirectional iterator category and
for container multimap<Key, T>, multimap<Key, T>::iterator is mutable
bidirectional iterator category. Is this correct?

Is my understanding wrong ?

Kindly clarify.

Thanks
V.Subramanian
 
I

Ian Collins

I am reading David Musser's "STL Tutorial and Reference Guide" Second
Edition.
In that book, on pages 68-69, definition has been given that "an
iterator can be mutable or constant depending on whether the result of
operator* is a reference or a constant reference."

As per this definition, on page 71 in this book, it is mentioned that
for 'set' and 'multiset', both the iterator and const_iterator types
are constant bidirectional types - in fact they are the same type.

The reason given in this book is as follows:

set<int> s;
s.insert(3);
s.insert(5);
s.insert(7);
set<int>::iterator i = s.begin();
*i = 4; // incorrect

On page 72, it is given that for container set<T>, set<T>::iterator is
constant bidirectional iterator category and for container
multiset<T>, multiset<T>::iterator is constant bidirectional iterator
category.

My understanding:
Along the same above discussion, shouldn't map<Key, T>::iterator and
multimap<Key, T>::iterator also be constant bidirectional iterators ?
(This is what I expected because for both set, multiset, map,
multimap, the key is constant)
No, the key may be constant, but the value is mutable.
 
G

Greg Herlihy

No, the key may be constant, but the value is mutable.

The salient difference between a std::map and a std::set is that each
value stored in a std::set is also a key. So the reason why values
stored in a std::set are immutable - is because the std::set's keys
are immutable (to ensure a proper order). But since the std::set's
keys and its values are one and the same, it follows that a std::set's
values are immutable because they are also keys..

With a std::map, the values are distinct from their keys - so although
the keys in a std::map are immutable, the values in a map need not be.
Because - unlike a std::set - changing a value stored in a std::map
will not affect the sorted order of the container.

Greg
 
D

dizzy

My understanding:
Along the same above discussion, shouldn't map<Key, T>::iterator and
multimap<Key, T>::iterator also be constant bidirectional iterators ?
(This is what I expected because for both set, multiset, map,
multimap, the key is constant)

However in this book, it is mentioned that for container map<Key, T>,
map<Key, T>::iterator is mutable bidirectional iterator category and
for container multimap<Key, T>, multimap<Key, T>::iterator is mutable
bidirectional iterator category. Is this correct?

Is my understanding wrong ?

Kindly clarify.

To add some more info to what Ian and Greg already told you, each standard
container has a nested typedef named "value_type" which represents the type
of the values stored in the container (and the iterator are just "like"
pointers to "value_type", so when you dereference an iterator you get
either a "value_type&" or a "value_type const&" depending if it is a
mutable iterator or not).

std::set<Key> defines value_type to be Key so the fact that both iterator
and const_iterator operator* return "value_type const&" means both iterator
types are not mutable. However, for std::map<Key, Value>, value_type is
std::pair<Key const, Value> (that's why you need all those "iter->second"
expressions to refer to the pointed to value) and const_iterator::eek:perator*
returns a "value_type const&" while iterator::eek:perator* returns
a "value_type&" so technically the later is a mutable iterator while the
former is not.

But, even so, you cannot change the Key pointed to by an mutable map
iterator because the mutable iterator will just give you access to
a "std::pair<Key const, Value>&" so you cannot modify the Key part of the
pair. Which means that while technically map<Key, Value>::iterator is a
mutable iterator, logically it is "semi-mutable" because it allows you
mutable access only to the value part.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,701
Latest member
XavierQ83

Latest Threads

Top