Iteration over std::vector: unsigned vs signed index variable
What is the correct way of iterating over a vector in C++?
Consider these two code fragments, this one works fine:
for (unsigned i=0; i < polygon.size(); i++) {
sum += polygon[i];
}
and this one:
for (int i=0; i < polygon.size(); i++) {
sum += polygon[i];
}
which generates warning: comparison between signed and unsigned integer expressions
.
I'm new in the world of C++, so the unsigned
variable looks a bit frightening to me and I know unsigned
variables can be dangerous if not used correctly, so - is this correct?
Iterating Backwards
See this answer.
Iterating Forwards
This 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 << someVector[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.
Four years passed, Google gave me this answer. With the standard C++11 (aka C++0x) there is actually a new pleasant way of doing this (at the price of breaking backward compatibility): the new auto
keyword. It saves you the pain of having to explicitly specify the type of the iterator to use (repeating the vector type again), when it is obvious (to the compiler), which type to use. With v
being your vector
, you can do something like this:
for ( auto i = v.begin(); i != v.end(); i++ ) {
std::cout << *i << std::endl;
}
C++11 goes even further and gives you a special syntax for iterating over collections like vectors. It removes the necessity of writing things that are always the same:
for ( auto &i : v ) {
std::cout << i << std::endl;
}
To see it in a working program, build a file auto.cpp
:
#include <vector>
#include <iostream>
int main(void) {
std::vector<int> v = std::vector<int>();
v.push_back(17);
v.push_back(12);
v.push_back(23);
v.push_back(42);
for ( auto &i : v ) {
std::cout << i << std::endl;
}
return 0;
}
As of writing this, when you compile this with g++, you normally need to set it to work with the new standard by giving an extra flag:
g++ -std=c++0x -o auto auto.cpp
Now you can run the example:
$ ./auto
17
12
23
42
Please note that the instructions on compiling and running are specific to gnu c++ compiler on Linux, the program should be platform (and compiler) independent.
In the specific case in your example, I'd use the STL algorithms to accomplish this.
#include <numeric>
sum = std::accumulate( polygon.begin(), polygon.end(), 0 );
For a more general, but still fairly simple case, I'd go with:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
std::for_each( polygon.begin(), polygon.end(), sum += _1 );
链接地址: http://www.djcxy.com/p/78756.html
上一篇: 在C ++中堆或堆栈上的变量创建