The behaviour of your program is undefined. Period.
A segmentation violation is only one possible consequence of undefined behaviour. Another possible consequence is seeming to behave "correctly", however you might define that notion.
Practically, a segmentation violation results from a unix host system detecting your program accessing memory it shouldn't, and sending a signal SIGSEGV
to your program, which in turn causes your program to terminate. The detection by the operating system is not fool-proof, so it may not detect all instances of your program going out of bounds - for example, if modifying a non-existent element of a vector modifies some area of memory allocated by your program for another variable.
A std::vector
s operator[]()
is not specified as throwing an exception, so temp[n]
where n
is outside the range 0
to temp.size()-1
is not required to throw an exception. It will have undefined behaviour. temp.at()
will throw an exception given a value outside the range 0
to temp.size()-1
, but operator[]
will is not required to.
Calling temp.reserve(8)
does not affect temp.size()
. temp.reserve()
affects temp.capacity()
, and the only constraint is that temp.capacity() >= temp.size()
. Since, in your example, temp.size()
is zero (that is achieved by the default constructor) there is no guarantee that usage of temp[n]
can access the reserved memory if n
is between 0
and 7
. The behaviour is still undefined according to the standard. It may seem to "work" or it may not.
When temp.capacity() > temp.size()
, one possible implementation of std::vector::reserve()
would be to mark additional memory inaccessible (all elements from temp.size()
to temp.capacity() - 1
) and trigger an error condition in your code for every usage of temp[n]
when n
is out of bounds. Such an implementation would require temp.resize()
(and other operations that affect size of the vector) to mark elements accessible between 0
and temp.size() - 1
. There is no requirement that an implementation do that - so your code behaving as you see is permitted. Equally, however, there is nothing preventing an implementation doing what I describe - so failing on any statement after temp.reserve()
in your code is also permitted.
Your testing seems to indicate that accessing elements up to temp.capacity()
- possibly even more - will "work". That is specific to your compiler and standard library, at the time you tested. It is not guaranteed by the standard, and your code could easily break in future (e.g. when the compiler or standard library are updated to a newer version).