Vector converted all negative values to zero

2019-04-17 19:44发布

问题:

I made a vector of constant size to store negative values, and then printing the values all I got was zeroes. I just want to know why it is not storing negative values.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v(5);
    v.push_back(-1);
    v.push_back(-2);
    v.push_back(-3);
    v.push_back(-4);
    v.push_back(-5);

    for (int i=0; i<5; i++)
       std::cout << v[i] << " ";  // All I got was zeroes
}

回答1:

That's because push_back puts new elements onto the end of the vector.

You can see the effect by running i to 9: the negative numbers will occupy v[5] to v[9].

Writing

std::vector<int> v{-1, -2, -3, -4, -5};

instead is a particularly elegant fix.



回答2:

The constructor that you invoke fills the first 5 elements with zeros, see here (#3 in the list of overloads):

Constructs the container with count default-inserted instances of T

(where the "default-inserted instance" of an int is 0). What you might have wanted is

std::vector<int> v;

v.reserve(5); /* Prevent unnecessary allocations as you know the desired size. */

v.push_back(-1);
/* ... */

An alternative using the original constructor call is

#include <numeric>

std::vector<int> v(5);

std::iota(v.rbegin(), v.rend(), -v.size());

though this does more work than necessary as every element is first default constructed and then assigned to a new value again.



回答3:

This is a case where the DRY principle would help you understand your mistake.

vector<int> v(5);

...

for(int i=0;i<5;i++)

Here you are creating an array, for which you think you reserve space for 5 elements. Then you insert those 5 elements. After that you wanted to print contents of the whole array, but instead of just writing v.size(), you repeated the 5, so that your code now reads like "Print first five elements of v", instead of "Print all elements of v".

If you instead wrote what you mean, you'd see that the array actually has 10 elements, not 5.

BTW, since C++11 you can loop over all elements in a more straightforward way:

for(int x : v)

or, if the elements were some more copy-expensive type, you could use references to the elements, even auto-type references:

for(auto& x : v)

This new for-loop syntax is called the range-based for loop.



回答4:

You can consider the vector a flexible version of the primitive array in C/C++. When you initialize a vector with a size n, the constructed vector has size of n (or maybe larger in the memory, but you don't know since it's implicitly handled by compiler). Note that here n represents the number of entries, but not the actual memory usage (i.e. bytes). If you do not initialize it with a size parameter, the vector is empty with size 0, but in the memory it would have some implicit default memory size.

Let's say your current vector has size 5. And you want to push_back() in another element, then the vector internally will reallocate the entire array into a new memory location which could hold all its old entries plus the new one. So you don't need to reallocate the memory manually by yourself, like what you have to do in C.

Here, in your example, to fill in those 5 negative integers in your vector, there are a couple of ways.

1) You can initialize a vector without specifying the size. And then push in each element you want.

vector<int> v;
for (int i = -1; i >= -5; --i) {
    v.push_back(i);
}

2) You can initialize the vector in your way with that size parameter. And then assign them with new values.

vector<int> v(5);
for (int i = 0; i < v.size(); ++i) {
    v[i] = -i;
}

3) You can also initialize the vector with those entries when it is constructed.

    vector<int> v{-1, -2, -3, -4, -5};
or  vector<int> v = {-1, -2, -3, -4, -5};


回答5:

When you declared the vector with

std::vector<int> v(5);

You made v store five 4-byte spaces in memory (assuming an int = 4 bytes on your system), and by default all of these 4-byte spaces store the bits representing 0's. Then, you pushed 5 more ints (-1, -2, -3, -4, -5) onto the end of the vector with:

v.push_back(-1);
v.push_back(-2);
v.push_back(-3);
v.push_back(-4);
v.push_back(-5);

At this point the vector has 10 elements, the first five being the unknown ints that happen to store 0's on the instance you ran the program. Since your for loop prints the first five elements in the vector, this is why it printed all 0's.