Is it legal to use a reverse_iterator with std::equal?
For example, are any of these legal?
std::equal(v.begin(), v.end(), w.rbegin())
std::equal(v.rbegin(), v.rend(), w.begin())
std::equal(v.rbegin(), v.rend(), w.rbegin())
All are valid, because reverse iterators are, in fact, forward iterators.
"Reverse iterator" is not an iterator category.
Remember some iterator categories:
An iterator that can be dereferenced (*) and incremented (++) is a forward iterator.
A forward iterator that can also be decremented is a bidirectional iterator.
A random access iterator is a biderectional iterator that also has + and - operators.
On the other hand, a reverse iterator is a bidirectional iterator or a random access iterator that looks at a collection in reverse. Look at
http://www.cplusplus.com/reference/std/iterator/reverse_iterator/
... especially what it says about iterator_category under the "Member types" heading.
Related
In the description of std::vector on cppreference (http://en.cppreference.com/w/cpp/container/vector/begin), I miss the categorization of the iterator (according to http://www.cplusplus.com/reference/iterator/) that is returned by the begin() function (the same applies for the iterator returned by end()).
Does cppreference not have to state which category of iterator is returned by begin() so that the user knows the iterator's functionality?
Currently, for me, it remains unclear which functionality std::vector's iterators provide.
Look at the main desciption of std::vector under the section Member types:
iterator RandomAccessIterator
const_iterator Constant random access iterator
reverse_iterator std::reverse_iterator<iterator>
const_reverse_iterator std::reverse_iterator<const_iterator>
std::vector uses RandomAccessIterator
A RandomAccessIterator is a BidirectionalIterator that can be moved to
point to any element in constant time. A pointer to an element of an
array satisfies all requirements of RandomAccessIterator
...
On the cppreference page for std::vector you will find:
Member types
============
...
iterator RandomAccessIterator
From here http://en.cppreference.com/w/cpp/container/vector you can see that a vector's iterators model the RandomAccessIterator concept: http://en.cppreference.com/w/cpp/concept/RandomAccessIterator
std::vector::begin() returns a std::vector::iterator (or const_iterator)
std::begin(x) returns the result of x.begin()
Therefore std::begin(std::vector<...>) will return a random access iterator.
I have a map definition and subsequent manipulation like this.
map<int,string> m;
m.insert(std::pair<int,string>(1,"A");
m.insert(std::pair<int,string>(2,"B");
m.insert(std::pair<int,string>(3,"C");
m.insert(std::pair<int,string>(4,"D");
auto it = m.find(2);
m.erase(m.find(3));
cout<< it->second;
Will "it" be valid after an erase to some other element ?
Will "it" be valid after an erase to some other element ?
Yes, std::map::erase will only invalidate references and iterators to the erased elements.
References and iterators to the erased elements are invalidated. Other references and iterators are not affected.
Note the code m.erase(m.find(3)); has a potential problem, since std::map::find will return end() iterator if nothing is found, but end() iterator cannot be used with std::map::erase.
The iterator pos must be valid and dereferenceable. Thus the end()
iterator (which is valid, but is not dereferencable) cannot be used as
a value for pos.
Yes it will. Only the erased iterator is invalidated when a map erase is performed.
am beginner to c++ and i want to know how operator ++ moves iterator backward. As i know iterator.begin() and iterator.end() returns pointer to fist index and last index respectively.
vector<int>::iterator it = myvector.begin();
when we do it++ it will move to next index. this is clear to me but i am completely confused with reverse iterator.
vector<int>::reverse_iterator rit = myvector.rbegin();
when we do rit++ it will move to backward. I want know how this is implemented in case of reverse iterator. Is it operator overloading or something which i don't know. Please give me right way to understand these things.
please give more detail knowledge.
_***************_
^begin ++---> ^end
^rend <---++ ^rbegin
As i know iterator.begin() and iterator.end() returns pointer to fist index and last index respectively.
Close, but not necessarily:
they return iterators, not pointers....
end() returns an iterator that's notionally "past" the last valid index.
Internally the vector iterators normally do store pointers though, and a ++ or -- on the iterator goes through a forwarding overloaded operator to perform a corresponding ++ or -- on the pointer.
For reverse iterators, the overloaded operator++ simply performs a -- on the pointer, and vice versa. For example, the Visual C++ library on my computer does this in class _Revranit, from which reverse_iterator is derived:
_Myt& operator++()
{
--current;
return (*this);
}
_Myt operator++(int)
{
_Myt _Tmp = *this;
--current;
return (_Tmp);
}
When you do it++ or rit++ they don't really mean "move forward or backward in the collection", they both mean "move to the next element you want to iterate over".
If you use begin(), you're saying "I want to iterate forwards", so it++ moves forwards.
If you use rbegin(), you're saying "I want to iterate backwards", so rit++ moves backwards.
Yes, this is operator overloading. When you do rit++, the compiler internally translates that do
rit.operator++(0);
Here, operator++ is a method of the reverse iterator class that knows how to move the iterator. The dummy integer argument is needed to differentiate between prefix and postfix operator++.
Yes, there's a reverse_iterator::operator++ overload which advances "backwards" from the last element to one-before-the-beginning.
The behavior is equivalent to (the page on cppreference might contain another possible implementation)
reverse_iterator operator++(int)
{
reverse_iterator __tmp(*this);
--current; // This is an internal iterator
return __tmp;
}
Notice that how this is exactly accomplished might vary from implementation to implementation. As far as you comply with the standard requirements, you have some degrees of freedom.
The relationship between a reverse iterator r and the iterator i it is constructed from is:
&*r == &*(i-1)
If end is the one-past-the-end element in a sequence, then the first element in the reversed sequence points to *(end – 1 )
template <class InputIterator, class Distance>
void advance (InputIterator& it, Distance n);
InputOutput < Forward < Bidirectional < Random Access
map<int, int> mapInts;
...
std::map<int, int>::iterator it = mapInts.begin();
std::advance (it,5);
Q> What is the type of iterator the map.begin returns? InputOut, Forward, Bidirectional?
Thank you
From Map::begin() documentation
std::map.begin()
Return iterator to beginning
Returns an iterator referring to the first element in the map container.
Because map containers keep their elements ordered at all times, begin points to the element that goes first following the container's sorting criterion.
If the container is empty, the returned iterator value shall not be dereferenced.
Return Value:
An iterator to the first element in the container.
If the map object is const-qualified, the function returns a const_iterator. Otherwise, it returns an iterator.
Member types iterator and const_iterator are bidirectional iterator types pointing to elements (of type value_type).
Notice that value_type in map containers is an alias of pair.
EDIT: by courtesy of #Andy Prowl:
Per C++ standard § 23.2.4/6
iterator of an associative container is of the bidirectional iterator category
I have the following code:
int main()
{
vector<int> v;
for(int i = 0; i < 10; ++i)
v.push_back(i);
auto it = v.begin() + 3;
cout << "Iterator: " << *it << endl;
vector<int>::reverse_iterator revIt(it);
cout << "Reverse iterator: " << *revIt << endl;
}
After running this code I get the following output:
Iterator: 3
Reverse iterator: 2
Could someone explain why the 2 values differ ?
Reverse iterators 'correspond' to a base iterator with an offset of one element because of how rbegin() and rend() have to be represented using base iterators that are valid (end() and begin() respectively). For example, rend() cannot be represented by an interator that 'points' before the container's begin() iterator, although that's what it logically represents. So rend()'s 'base iterator' is begin(). Therefore, rbegin()'s base iterator becomes end().
A reverse iterator automatically adjusts for that offset when it is dereferenced (using the * or -> operators).
An old article by Scott Meyers explains the relationship in detail along with a nice picture:
Guideline 3: Understand How to Use a reverse_iterator’s Base iterator
Invoking the base member function on a reverse_iterator yields the
“corresponding” iterator, but it’s not really clear what that means.
As an example, take a look at this code, which puts the numbers 1-5 in
a vector, sets a reverse_iterator to point to the 3, and sets an
iterator to the reverse_iterator’s base:
vector<int> v;
// put 1-5 in the vector
for (int i = 1; i <= 5; ++i) {
v.push_back(i);
}
// make ri point to the 3
vector<int>::reverse_iterator ri =
find(v.rbegin(), v.rend(), 3);
// make i the same as ri's base
vector<int>::iterator i(ri.base());
After executing this code, things can be thought of as looking like
this:
This picture is nice, displaying the characteristic offset of a
reverse_iterator and its corresponding base iterator that mimics the
offset of rbegin() and rend() with respect to begin() and end(), but
it doesn’t tell you everything you need to know. In particular, it
doesn’t explain how to use i to perform operations you’d like to
perform on ri.
Looks like the documentation says they do that to handle past-the-end elements, i.e. if you reverse an iterator that is past the end, the new reverse iterator points to the last element.
The first paragraph of 24.5.1 Reverse iterators says:
Class template reverse_iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence. The fundamental relation between a reverse iterator and its corresponding iterator i is established by the identity:
&*(reverse_iterator(i)) == &*(i - 1).
The value returned by rend() cannot point before begin(), because that is not valid. So it was decided that rend() should contain the value of begin() and all other reverse iterators be shifted one position further. The operator* compensates for this and accesses the correct element anyway.
Reverse iterator looks always "one before" then the forward, since its range is shifted by one:
Forward iterator goes from begin() (the first element) to end() (past the last: [begin-end) is opened at the end side)
Reverse iterator goes from rbegin() { return reverse_iterator(end()); } to rend() { return reverse_iterator(begin()); } by definition, but also has to walk the open range [rbegin-rend) having rbegin to be the last (not "past the last") and rend to be "before the first" (not "the first") hence a 1 difference to be accommodated.