Reputation: 437
I saw in some very well known books on C++ that --
vector<int> ivec;
for (vector<int>::size_type i = 0; i != 10; ++i) {
ivec.push_back(i);
ivec.push_back(i); // duplicate copies of each number
}
I was wondering why vector<int>::size_type
is used here. They are not
comparing i
with size of the vector. Intent is to insert 10 int
's in the
vector, so int i = 0
would be a right thing to do, isn't it ?
vector<int>::size_type
would be typedef
for std::size_t
which in turn will
be unsinged int
, but here we are storing int
's in the vector
.
Please clarify my understanding about vector<int>::size_type
. Is it fair to use it in the for loop above ?
Upvotes: 2
Views: 2009
Reputation: 385194
Yes, your value type is int
.
But that's not what size_type
is talking about. size_type
is the type of the indices of the vector. It's the type of the size of the vector (hence its name!).
We use a type alias for this (provided by the standard library) because it may/will differ across systems. It'll often be a size_t
, which itself is a standard alias for some big unsigned type, albeit which one you cannot predict in general for a portable program.
This particular example is doubly confusing, because the book author really is populating vector values using the size type. This is not necessarily "wrong": in the range 0-9, it's not going to break. The compiler will just implicitly convert the integers in the usual way.
But it is expressing intent incorrectly.
I imagine it used to look like this:
vector<int> v(5);
for (vector<int>::size_type i = 0; i < v.size(); i++)
v[i] = 42;
Then somebody has changed the loop body (such that i
now is used for values, rather than for indices) and not thought about changing the loop preamble.
Making i
an int
would be far more clear and obvious.
Overall I'd consider avoiding these "well-known books" or, at least, checking their errata to see whether the code has been adjusted post-publication, because that's quite a strange example of C++.
Upvotes: 0
Reputation: 26302
To avoid implicit casts and compiler warnings you can be explicit about what you push_back
:
vector<int> ivec;
for (vector<int>::size_type i = 0; i != 10; ++i) {
ivec.push_back(static_cast<int>(i));
ivec.push_back(static_cast<int>(i));
}
Using size_type
and static_cast
in this code seems to be artificial. It would be more meaningful in the following example (a combination of @AlanBirtles's examples):
vector<int> ivec(20);
for (vector<int>::size_type i = 0; i != 10; ++i) {
ivec[2 * i] = ivec[2 * i + 1] = static_cast<int>(i);
}
Upvotes: 0
Reputation: 36399
I'd say no, this code is not correct and many compilers will warn about the implicit cast from size_t
to int
.
vector::size_type
/size_t
should always be used for vector indexes but if you have a vector
of int
then you should be inserting int
s into it.
The correct code would be:
vector<int> ivec;
for (vector<int>::value_type i = 0; i != 10; ++i) {
ivec.push_back(i);
ivec.push_back(i); // duplicate copies of each number
}
for (vector<int>::size_type i = 0; i < ivec.size(); ++i) {
std::cout << ivec[i] << "\n";
}
Upvotes: 4
Reputation: 986
Basically, the above code is 'fine' in the sense that it compiles and does the intended job, as others have said.
When they said the intent was to insert ten int
s in the vector, the int
s are guaranteed positive because of how the loop is formatted, so the unsigned int
will just convert into int
.
However, I don't believe this is good practice as you said - the size type has nothing to do with the type of the elements being inserted - the size type is basically always an unsigned int
. Just using int
or value_type
would obviously make the intent of the code clearer.
Upvotes: 5