Currently learning C++ and stumbled upon this problem
std::vector<int> example;
example[0] = 27;
std::cout << example[0];
This crashes the program, but if I define a size std::vector<int> example(1)
it works fine. What I also noticed was that if I use example.push_back(27)
instead of example[0] = 27
without defining the size it also works fine. Is there a reasoning behind this?
An empty vector has no elements allocated in memory.
You should use example.push_back(27)
instead of trying to subscript it. push_back()
allocates a new element and then adds it to the vector. Once that new element is added to the vector, it can be reassigned using example[0] = something
.
The reason is very simple: an empty vector has no elements so you may not use the subscript operator. No memory was allocated and no element was created that you could access it with the subscript operator
As for the method push_back
then it adds an element to the vector.
Also using the constructor the way you wrote
std::vector<int> example(1)
creates a vector with one element.
To be more specific, you're using the default constructor so the vector is not obligated to allocate any memory (because you did not ask it to).
So if you run the following code:
std::vector<int> e;
cout<< e.size() << endl;
cout<< e.capacity() << endl;
It'll print 0 and 0. So the size
is 0
And as the documentation states:
If the container size is greater than n, the function never throws
exceptions (no-throw guarantee). Otherwise, the behavior is undefined.
e.push_back(5);
std::cout << e[0];
Would work.
From: http://www.cplusplus.com/reference/vector/vector/operator[]/
std::vector::operator[]
Access element
Returns a reference to the element at position n in the vector container.
A similar member function, vector::at, has the same behavior as this operator function, except that vector::at is bound-checked and signals if the requested position is out of range by throwing an out_of_range exception.
Portable programs should never call this function with an argument n that is out of range, since this causes undefined behavior.
This can get confusing in STL since std::map, for example:
std::map<int, std::string> myMap;
myMap[0] = "hello"
will create the mapping if one does not already exist.