Reputation: 10911
I have a vector declared as
std::vector<int> MyVector;
MyVector.push_back(5);
MyVector.push_back(6);
MyVector.push_back(7);
How do should I use it in a for loop?
By iterating it with an iterator?
for (std::vector<int>::iterator it=MyVector.begin(); it!=MyVector.end(); ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}
Or by its access iterator?
for (std::vector<int>::size_type i=0; i<MyVector.size(); i++)
{
std::cout << "Vector element (i) : " << MyVector.at(i) << std::endl;
}
In examples I found on internet both of them are used. Is one of them superior to the other under all conditions? If not, when should I prefer one of them over the other?
Upvotes: 5
Views: 1768
Reputation: 153909
There is no "one is superior to the other" (except that you almost never
want to use at()
—at()
is only appropriate if there is
something you can really do to recover from the error). The use of
iterator vs. index is largely one of style, and the message you're
passing. The more idiomatic C++ way of doing things would be the
iterator, but people coming from other backgrounds (for example,
mathematicians) will find indexing more idiomatic.
There are where there is a real distinction:
The iterator idiom will work with other types of containers. This might be relevant if there is a real possibility that you use other containers.
The indexing idiom can use a single index for several different
containers. If you're iterating through several vector
with the same
size, using the indexing idiom makes it clearer that you're accessing
the same element in each of the vector
. (Again, this seems to occur
most often in mathematical applications.)
Finally, any time you're really doing random access, or calculating
the element in any way, using indexes is probably more intuitive. (In
such cases, you probably want to do the calculations in int
, only
converting to size_t
at the last moment.)
Upvotes: 1
Reputation: 206518
The first format is more generic format for iterating over standard library containers so it is more common and intuitive. If you need to change your container then this iterating code remains unimpacted.It will work for every standard library container type, thus it gives you more generic code.
In second format, std::vector::at()
checks for the bounds each time it gets called on every iteration, so it may be a little detrimental to performance. This overhead is not present in the first format as there is no bounds checking involved.Note that same is the case with using operator[]
.
Note the performance lag though is not as much as you will notice it unless you are operating on a huge data.
Upvotes: 5
Reputation: 17708
Using std::vector's [] operator
is probably faster because using std::vector::at()
inside a for loop checks the vector's size twice (in the for loop and in std::vector::at()'s bounds checking).
The first method can be used in other containers and thus can help you much when you change your container type.
If you use C++11, use range-based loops.
Upvotes: 3
Reputation: 52365
First if you have C++11, use a range-based for:
for (auto i : MyVector)
{
std::cout << i;
}
Or BOOST_FOREACH
in C++03:
BOOST_FOREACH(int& i, MyVector)
{
std::cout << i;
}
Or std::copy
:
std::copy(MyVector.begin(),
MyVector.end(),
std::ostream_iterator<int>(std::cout, "\n"));
As for, the question at hand, at()
checks that the index is within bounds and throws an exception if it isn't. So, do not use it unless you need that extra checking. The first way you have it is standard and works well. Some people are pedantic and even it write it like so:
for (std::vector<int>::iterator it=MyVector.begin(), end = MyVector.end(); it!= end; ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}
In the above I cached the end
iterator instead of calling end()
each loop. Whether this actually makes a performance difference or not, I don't know.
Upvotes: 2