Perhaps this question is trivial, but thinking a second time about it I wonder how to do the following really the right way:
std::vector<K> v = ...;
for(T i=0; i<v.size(); ++i) {
const K& t = v[i];
// use t *and i*
}
What type should T
be? int
, unsigned int
, int32_t
, size_t
(which would be the type of v.size()
) or any other suggestions? Please try to consider portability, error-proneness and performance and be objective in your answer.
Edit: I did not choose iterators, because it would also like to use the index number i explicitly.
The type of i
should be the same as the return value of size()
, which is std::vector<K>::size_type
. However, in practice, size_t
will do just fine. If you use a signed integer type, then your compiler will probably warn about a signed/unsigned mismatch in the less-than comparison.
Normally you would use an iterator for this anyway:
std::vector<K> v = ...;
for (std::vector<K>::iterator i = v.begin(); i != v.end(); ++i) {
const K& t = *i;
// use t
}
Or, in C++0x:
std::vector<K> v = ...;
for (auto i = v.begin(); i != v.end(); ++i) {
const K& t = *i;
// use t
}
In response to your comment about using the vector index with iterators, consider the std::distance()
function which is constant time operation for vector iterators:
std::vector<K> v = ...;
for (auto i = v.begin(); i != v.end(); ++i) {
const K& t = *i;
size_t index = std::distance(v.begin(), i);
// use t and index
}
The type returned by v.size
and expected by v[]
is std::vector<K>::size_type
.
However, consider using iterators instead : the risk of going out of bounds is lower, and you can use the standard library algorithms.
The type T usually doesn't matter as long as it is as large as the vector size.
In terms of performance, there should't be any differences.
In terms of error-proneness/portability, I suggest using signed integers, because if you somehow subtract values from i
, you'll get a large positive number, which is harder to check than a negative number. But because v.size()
is a size_t
, if you use a signed integer for T, and v
has ≥ 231 (or 263) items, the i
will have to become invalid before ending. But I think if the vector needs to be that ridiculously large (esp. on 64-bit platforms), there is other a bigger problem than which type T to choose.
Never use int32_t
for a counter.
(These are before OP's edit:)
But in your case you may want iterate with an iterator instead.
for (std::vector<K>::const_iterator cit = v.begin(); cit != v.end(); ++ cit) {
const K& t = *cit;
// ...
}
With Boost.Foreach you could turn this mess into
BOOST_FOREACH(const K& t, v) {
// ...
}
In C++0x this becomes a built-in feature (§[stmt.ranged]), but AFAIK no compilers supported it yet:
for (const K& t : v) {
// ...
}
But most compilers that claim to support C++0x should allow auto
:
for (auto cit = v.cbegin(); cit != v.cend(); ++ cit) {
const K& t = *cit;
// ...
}
or lambda expression:
std::for_each(v.cbegin(), v.cend(), [](const K& t) {
...
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With