work - vector c++




C++: “vector<int>::size_type variable”-what is the point of declaring in this way? (3)

I think this is a very basic question but I couldn't just figure it out.

I was used to using arrays in C++ but I'm now starting to learn vectors. I was making a test code, and I came across a question.

First of all, here's the code I made:

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

int main(){
  vector<double> score(10);

  for(vector<double>::size_type i=0;i<20;i++) {
    cout<<"Enter marks for student #"<<i+1<<":"<<flush;
    cin>>score[i];
  }

  double total = accumulate(score.begin(), score.end(),0);

  cout<<"Total score:"<<total<<endl<<"Average score:"<<total/score.size()<<flush;

  return 0;
}

In the for sentence in line #9, I am declaring i as a vector<double>::size_type type (because I was told to do so). I tested the code with the type said above replaced with an int, and it worked perfectly fine. Why is vector<double>::size_type preferred compared to int?


size_type is guaranteed to be large enough for the largest supported vector size, vector::max_size(). int is not: on many common platforms, int has 32 bits, while max_size() is considerably larger than 231.

If you know the size is (and will always be) a small number like 20, then you can get away with using int or any other integer type instead of size_type. If you were to change the program, for example to read the size from the input, then it would go horribly wrong if that value were larger than INT_MAX; while using size_type, it would continue working for any value up to max_size(), which you can easily test for.


The vector size_type is what's used by vector to do size comparisons. If you had a loop that used an int as a counter and compared against the vector's actual size, you'd get warnings from the compiler about signed vs. unsigned integer comparisons:

for( int i=0; i<score.size(); i++ ){  // <-- signed vs. unsigned comparisons
    // do something...
}

Your problem is two fold.

First, you are writing beyond the end of the std::vector -- the std::vector has 10 elements, and you are writing to 20.

In order to fix this, and to follow the Don't Repeat Yourself principle, you'd change your code as follows:

int main(){
  std::vector<double> score(20);

  for(std::vector<double>::size_type i=0;i<score.size();i++) {

where I both made the vector larger and used its size to determine how much to write.

Now, when we try to replace that long clause with int:

int main(){
  std::vector<double> score(20);

  for(int i=0;i<score.size();i++) {

we get a singed/unsigned comparison (probably):

i<score.size()

where score.size() is an unsigned value of type std::vector<double>::size_type, and i is an int.

Compilers often give warnings in these cases, as it is really easy to get nonsensical results (if i < 0, the comparison will usually result in the negative number comparing larger than the positive one!) In addition, if the size of the vector is larger than the max value of int (on some systems, as small as 32767, usually at least 2147483647, and sometimes much larger -- this is a value the compiler is reasonably free to pick for itself, the C++ standard does not specify it fully), the loop will fail spectacularly.

Now, while the type of std::vector<double>::size() is std::vector<double>::size_type, this is (in every implementation I've experienced) just std::size_t. So that is a shorter way to say it:

  for(std::size_t i=0;i<score.size();i++) {

(std::size_t is defined in <cstddef> as an aside).

If you are programming in C++11, you can do one better:

int i=0;
for(double& student:score) {
  std::cout<<"Enter marks for student #"<<++i<<":"<<std::flush;
  std::cin>>student;
}

which is a range-based for loop and avoid the problem of indexing entirely.





std