-3

Why does the following work? I thought that writing to an an index of a vector object beyond the end of the vector object would cause a segmentation fault.

#include <iostream>
#include <vector>
using namespace std;
int main() {
  vector<int> x(1);
  x[10] = 1;
  cout << x[10] << endl;
}

What are the implications of this? Is there a safer way to initialize a vector of exactly n elements and write only to those? Should I always use push_back()?

castle-bravo
  • 1,389
  • 15
  • 34
  • 6
    It doesnt work. Youre writing out of bounds this is undefined behavior. – Borgleader Apr 10 '15 at 01:53
  • 3
    Undefined behavior means *it's undefined what will happen*. It might appear to work, it might crash horribly, it might make [demons fly from your nostrils](http://www.urbandictionary.com/define.php?term=nasal+demons). – Mark Ransom Apr 10 '15 at 02:05
  • @MarkRansom Interesting reference, I originally thought you were being creative. – Borgleader Apr 10 '15 at 02:12
  • @MarkRansom [It can also make you pregnant.](http://stackoverflow.com/a/1553407/922184) – Mysticial Apr 10 '15 at 02:12
  • 1
    @Borgleader oh I wish I was that clever. Probably the last creative thing I did was my avatar pic, and even that was totally derivative. – Mark Ransom Apr 10 '15 at 02:17
  • 1
    You can use the [`.at()`](http://en.cppreference.com/w/cpp/container/vector/at) method to access an element with bounds checking. – Borgleader Apr 10 '15 at 02:23
  • 1
    Amazing how questions are voted down because the person asking them does not know the answer. – Dino Dini Nov 24 '20 at 21:59

2 Answers2

3

Somebody implementing std::vector might easily decide to give it a minimum size of 10 or 20 elements or so, on the theory that the memory manager likely has a large enough minimum allocation size that it will use (about) the same amount of memory anyway.

As far as avoiding reading/writing past the end, one possibility is to avoid using indexing whenever possible, and using .at() to do indexing when you truly can't avoid it.

I find that I can usually avoid doing indexing at all by using range-based for loops and/or standard algorithms for most tasks. For a trivial example, consider something like this:

int main() {
    vector<int> x(1);
    x.push_back(1);

    for (auto i : x)
        cout << i << "\n";
}

.at() does work, but I rarely find it useful or necessary--I suspect I use it less than once a year on average.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

So under the covers what actually happens when you try to address an element of an array or vector that is outside the container's bounds is a memory dereference to a piece of memory that is not part of the container. However, reads and writes to this location can "work" or appear to work because it is just more memory that you are reading/writing to. You are doing something very very bad. You will generally see random junk when accessing memory outside of your bounds because it can belong to something else or is leftovers from a previous process because the memory controller will not naturally zero out memory on its own. So the best practice is to use the size of the container to check your reads and writes if you are ever in doubt as to if you are outside the bounds of the container. You can use vector.size() to find the current size of the container.

NKamrath
  • 536
  • 3
  • 9