Reputation: 133112
I need to iterate over a vector from the end to the beginning. The "correct" way is
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
//do Something
}
When //do Something
involves knowing the actual index, then some calculations need to be done with rit
to obtain it, like index = v.size() - 1 - (rit - v.rbegin)
If the index is needed anyway, then I strongly believe it is better to iterate using that index
for(int i = v.size() - 1; i >= 0; --i)
{
//do something with v[i] and i;
}
This gives a warning that i
is signed and v.size()
is unsigned.
Changing to
for(unsigned i = v.size() - 1; i >= 0; --i)
is just functionally wrong, because this is essentially an endless loop :)
What is an aesthetically good way to do what I want to do which
Upvotes: 44
Views: 41904
Reputation: 2075
You can cast the size to an int if your vector is not huge
for (int i = int(v.size()) - 1; i >= 0; --i) {
//do something with v[i] and i;
}
Upvotes: 0
Reputation: 12821
In C++20 one can use ranges (#include <ranges>
)
//DATA
std::vector<int> vecOfInts = { 2,4,6,8 };
//REVERSE VECTOR
for (int i : vecOfInts | std::views::reverse)
{
std::cout << i << " ";
}
or if it is required to save in a different variable.
//SAVE IN ANOTHER VARIABLE
auto reverseVecOfInts = std::views::reverse(vecOfInts);
//ITERATION
for (int i : reverseVecOfInts)
{
std::cout << i << " ";
}
Upvotes: 5
Reputation: 196
for (it = v.end()-1; it != v.begin()-1; --it)
{
}
The "goes to" operator definitely messes with my head.
Upvotes: -3
Reputation: 163357
As you've noted, the problem with a condition of i >= 0
when it's unsigned is that the condition is always true. Instead of subtracting 1 when you initialize i
and then again after each iteration, subtract 1 after checking the loop condition:
for (unsigned i = v.size(); i-- > 0; )
I like this style for several reasons:
i
will wrap around to UINT_MAX
at the end of the loop, it doesn't rely on that behavior — it would work the same if the types were signed. Relying on unsigned wraparound feels like a bit of a hack to me.size()
exactly once.>=
. Whenever I see that operator in a for
loop, I have to re-read it to make sure there isn't an off-by-one error.Upvotes: 66
Reputation: 33655
to be aesthetically pleasing! ;)
for(unsigned i = v.size() - 1; v.size() > i; --i)
Upvotes: 7
Reputation: 54178
There's nothing to stop your reverse_iterator
loop also using the index as described in multiple other answers. That way you can use the iterator or index as needed in the // do the work
part, for minimal extra cost.
size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin();
rit != v.rend(); ++rit, --index)
{
// do the work
}
Though I'm curious to know what you need the index for. Accessing v[index]
is the same as accessing *rit
.
Upvotes: 18
Reputation: 6566
loop condition i != std::numeric_limits<unsigned>::max()
... or use UINT_MAX
if you think its to verbose.
or another way:
for(unsigned j=0, end=v.size(), i=end-1; j<end; --i, ++j)
or
for(unsigned end=v.size(), i=end-1; (end-i)<end; --i)
Upvotes: 0
Reputation: 3505
Hi i think better way use iterator as you use in first sample and if you need get iterator index you can use std::distance to calculate it, if i understand your question
Upvotes: 0
Reputation: 7870
Try out a do while :
std::vector<Type> v;
// Some code
if(v.size() > 0)
{
unsigned int i = v.size() - 1;
do
{
// Your stuff
}
while(i-- > 0);
}
Upvotes: 0
Reputation: 22854
I would prefer the reverse iterator variant, because it's still easy to interpret and allows to avoid index-related errors.
Sometimes you can simply use the BOOST_REVERSE_FOREACH
, which would make your code look the following way:
reverse_foreach (int value, vector) {
do_something_with_the_value;
}
Actually speaking, you can always use foreach
statements for these kinds of loops, but then they become a bit unobvious:
size_t i = 0;
foreach (int value, vector) {
do_something;
++i;
}
Upvotes: 2
Reputation: 2320
I think that:
for(unsigned i = v.size() - 1; i >= 0; --i)
is fine if you check
!v.empty()
earlier.
Upvotes: -3