2

I wrote the following code to test the value of capacity of a vector when it was constructed from another. This was inspired by a question asked here.

#include <iostream>
#include<vector>
int main()
{
    std::vector<int> a;
    a.reserve(65536);
    a[0]=10;
    std::vector<int> b(a);  //NOTE: b is constructed from a
    std::cout<<a[0]<<"  " <<b[0];
}

The Program compiled successfully, but when it was run it threw the following error

 Error during execution:
         Segmentation Fault(core dumped).

Then to check that the value was initialized to vector a, I changed the code as shown below:

#include <iostream>
#include<vector>
int main()
{
    std::vector<int> a(65536);
    a[0]=10;
    std::vector<int> b(a);  //NOTE: b is constructed from a
    std::cout<<a[0];
}

This time the program ran successfully without errors and gave the output as:

Output: 
      10

I then tried to changed it to the following code :

#include <iostream>
#include<vector>
int main()
{
    std::vector<int> a(65536);
    a[0]=10;
    std::vector<int> b(a);  //NOTE: b is constructed from a
    std::cout<<a[0]<<"  " <<b[0];
}

and to my surprise the following output came as expected :

Output:
     10  10

I could not understand why the program ran successfully when the vector was initialized with it's size in the constructor but not when it's capacity was given using reserve().

I also came to know that the reserving capacity for vector using reserve() does not initialize the size of the vector. The following code also confused me further.

#include <iostream>
#include<vector>

int main()
{
    std::vector<int> a;
    a.reserve(1);
    for(int i=0;i<5;i++)
        a[i]=i;
    std::vector<int> b(a);  //NOTE: b is constructed from a
    for(int i=0;i<5;i++)
    std::cout<<a[i]<<"  ";
    std::cout<<"\n"<<a.size()<<"  "<<a.capacity();
 }

When executed it displays the following weird output:

Output:
     0  1  2  3  4
     0  1

The vector stored the 5 values but the size of the vector remained 0.

I couldn't understand this behaviour of vector. How could it take in values with the size not changing.

Community
  • 1
  • 1
kaartic
  • 523
  • 6
  • 24

3 Answers3

3

You're mixing up capacity and size. Capacity is just an implementation feature. It allows you to optimize memory allocation by specifying how many elements the vector will contain in the end, so its implementation doesn't have to re-allocate the memory each time the vector grows (the actual growth strategy is also an implementation detail).

Size is a logical thing. It defines how many elements are actually there. It must never exceed the capacity (and indeed the capacity will grow as necessary if the vector is resized beyond it).

Accessing elements outside of the 0 .. size - 1 range is illegal and may or may not break depending on your luck irregardless of whatever the capacity is. That's called undefined behavior.

So when you call a method or use a constructor you have to figure out whether it sets capacity or size.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
  • You are right, I actually didn't know at the start that the **operator[]** does not check for bounds when used, so I wasn't aware that it was undefined behaviour. – kaartic Jun 10 '16 at 07:21
2

This is not allowed, you just wrote outside of valid memory.

std::vector<int> a;
a.reserve(65536);
a[0]=10;

You'd need to use the constructor

std::vector<int> a(65536);
a[0]=10;

or resize

std::vector<int> a;
a.resize(65536);
a[0]=10;

or push_back

std::vector<int> a;
a.reserve(65536);
a.push_back(10);

reserve changes the available capacity of the vector, resize changes the actual size of the vector. You can read more about that here.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Addition: in the crash example (using reserve), a's size is still 0, and the copy constructor creates (legally!) an empty vector, obviously without having storage allocated. Check capacity for B in one of the running examples. It certainly will be less than 65536, as copying a vector means copying its contents (elements from 0 to size()), but capacity is not part of this semantics. – Aconcagua Jun 09 '16 at 12:38
1

reserve() of std::vector will pre-allocate for elements, but it doesn't mean elements are created, and accessing a[0] without creating an element is also illegal.

You can useresize() to create elements. Try this:

#include <iostream>
#include<vector>
int main()
{
    std::vector<int> a;
    a.resize(65536);
    a[0]=10;
    std::vector<int> b(a);  //NOTE: b is constructed from a
    std::cout<<a[0]<<"  " <<b[0];
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70