Iteration over std::vector: unsigned vs signed index variable
For iterating backwards see this answer.
Iterating forwards is almost identical. Just change the iterators / swap decrement by increment. You should prefer iterators. Some people tell you to use std::size_t
as the index variable type. However, that is not portable. Always use the size_type
typedef of the container (While you could get away with only a conversion in the forward iterating case, it could actually go wrong all the way in the backward iterating case when using std::size_t
, in case std::size_t
is wider than what is the typedef of size_type
):
Using std::vector
Using iterators
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
/* std::cout << *it; ... */
}
Important is, always use the prefix increment form for iterators whose definitions you don't know. That will ensure your code runs as generic as possible.
Using Range C++11
for(auto const& value: a) {
/* std::cout << value; ... */
Using indices
for(std::vector<int>::size_type i = 0; i != v.size(); i++) {
/* std::cout << v[i]; ... */
}
Using arrays
Using iterators
for(element_type* it = a; it != (a + (sizeof a / sizeof *a)); it++) {
/* std::cout << *it; ... */
}
Using Range C++11
for(auto const& value: a) {
/* std::cout << value; ... */
Using indices
for(std::size_t i = 0; i != (sizeof a / sizeof *a); i++) {
/* std::cout << a[i]; ... */
}
Read in the backward iterating answer what problem the sizeof
approach can yield to, though.
What should be the index type when iterating over the elements of a vector?
You should use std::vector<T>::size_type
1. Its unsigned integral type. Its usually same as size_t
.
To know the difference between size_type
and size_t
, see this topic:
- C++ for-loop - size_type vs. size_t
1. Similarly, you can use std::string::size_type
, std::list<T>::size_type
, std::deque<T>::size_type
, std::set<T>::size_type
, and so on. Almost all standard containers define a nested type called size_type
.
One can argue that you should use iterator instead of index. But I also see that sometime iterator makes the for-loop very wide horizontally, see this :
for(std::vector<std::vector<std::string> >::iterator it = v.begin(); it != v.end(); ++it)
{
}
It doesn't look. It in fact irritates sometimes. In such situations, some programmers prefers index over iterator.
In C++0x, iterator has been made more idiomatic. Now you can use iterator without making the syntax cumbersome:
for(auto it = v.begin(); it != v.end(); ++it)
{
}
Or even better, using range-based for loop:
for(auto & item : v)
{
}
Iterate through a C++ Vector using a 'for' loop
Is there any reason I don't see this in C++? Is it bad practice?
No. It is not a bad practice, but the following approach renders your code certain flexibility.
Usually, pre-C++11 the code for iterating over container elements uses iterators, something like:
std::vector<int>::iterator it = vector.begin();
This is because it makes the code more flexible.
All standard library containers support and provide iterators. If at a later point of development you need to switch to another container, then this code does not need to be changed.
Note: Writing code which works with every possible standard library container is not as easy as it might seem to be.
acceptable fix for majority of signed/unsigned warnings?
I made this community wiki... Please edit it. I don't agree with the advice against "int" anymore. I now see it as not bad.
Yes, i agree with Richard. You should never use 'int'
as the counting variable in a loop like those. The following is how you might want to do various loops using indices (althought there is little reason to, occasionally this can be useful).
Forward
for(std::vector<int>::size_type i = 0; i < someVector.size(); i++) {
/* ... */
}
Backward
You can do this, which is perfectly defined behaivor:
for(std::vector<int>::size_type i = someVector.size() - 1;
i != (std::vector<int>::size_type) -1; i--) {
/* ... */
}
Soon, with c++1x (next C++ version) coming along nicely, you can do it like this:
for(auto i = someVector.size() - 1; i != (decltype(i)) -1; i--) {
/* ... */
}
Decrementing below 0 will cause i to wrap around, because it is unsigned.
But unsigned will make bugs slurp in
That should never be an argument to make it the wrong way (using 'int'
).
Why not use std::size_t above?
The C++ Standard defines in 23.1 p5 Container Requirements
, that T::size_type
, for T
being some Container
, that this type is some implementation defined unsigned integral type. Now, using std::size_t
for i
above will let bugs slurp in silently. If T::size_type
is less or greater than std::size_t
, then it will overflow i
, or not even get up to (std::size_t)-1
if someVector.size() == 0
. Likewise, the condition of the loop would have been broken completely.
Why unordered_map not showing correct index values of a vector?
your for
loop has a wrong range. You start at element 1
and because of <=
only stop at the size of codeforces + 1
, which is out of bounds.
When iterating arrays the index starts at 0
and should end at size() - 1
. This can be easily achieved by saying < size()
as the less operator will result in false
if the index is at size()
- therefore size() - 1
is the last iteration step.
You have two options, either go from 1
to size()
and access [i - 1]
for(int i = 1; i <= x.size(); i++){
data[x[i - 1]].push_back(i);
}
or go from 0
to size() - 1
and push_back(i + 1)
for(int i = 0; i < x.size(); i++){
data[x[i]].push_back(i + 1);
}
I recommend the latter, as it's the common way to iterate arrays.
read here why you should avoid writing using namespace std;
.
Slow performance using std::distance to get std::map index
std::map
is a tree structure. It's not random access, and elements don't have indices, and the only way to advance through the tree is to follow the links, one at a time. Because of this, std::map::iterator
is a BidirectionalIterator. That means it only supports increment and decrement operations. It doesn't support any sort of difference operation. To get the difference between two of them you have to repeatedly increment the start iterator until it's equal to the end iterator. Something like this:
template <typename Iterator>
size_t distance(Iterator start, Iterator end)
{
size_t dist = 0;
while (start != end) {
++dist;
++start;
}
return dist;
}
Looking at that function, you can probably see why your loop is slow. Every time through the loop, std::distance
has to walk through the tree and count how far from the beginning it is. If you really need an index to go with your map, you'll need to maintain it yourself. std::map
doesn't seem like the right structure in that case though, since the indices will change as new elements are added.
C++, fast removal of elements from vector by binary index
Unfortunately there is no automatism for this. You simply have to implement a custom erase function yourself:
auto widx = numbers.begin();
for (auto ridx = numbers.cbegin(), auto bidx = idxs.cbegin();
ridx != numbers.end;
++ridx, ++bidx) {
if (*bidx) *widx++ = *ridx;
}
numbers.erase(widx, numbers.end());
Related Topics
Assigning Parsers to Auto Variables
C/C++ Check If One Bit Is Set In, I.E. Int Variable
Resolution of Std::Chrono::High_Resolution_Clock Doesn't Correspond to Measurements
Meaning of = Delete After Function Declaration
C++, Variable Declaration in 'If' Expression
C++: Constructor Initializer For Arrays
How to Check If a Std::Thread Is Still Running
Efficient Way of Storing Huffman Tree
Difference in Floating Point Arithmetics Between X86 and X64
How to Use Reference Parameters in C++
Non-Blocking Worker - Interrupt File Copy
Rotate an Image Without Cropping in Opencv in C++
Why Is C++11'S Pod "Standard Layout" Definition the Way It Is
How to Generate a Calling Graph For C++ Code
Const& , & and && Specifiers For Member Functions in C++