1

Here's the code:

vector<double> samples;

int main()
{
    samples.resize(100);
    for(int i=0; i<100; i++) {
        samples[i]=i/100.0;
    }

    samples.clear();
    cout << "vector size: " << samples.size() << endl;
    cout << "... but samples[9]=" << samples[9] << endl;
}

And the output it:

vector size: 0
... but samples[9]=0.09

After clearing the vector (size is 0) I can still access to its data. Is it that normal?

Reference says elements will be "destroyed", but it seems it doesn't mean "default/empty" values.

In other languages I would get a "out of range" error message at runtime...

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 1
    Have you tried to use `samples.at(9)`? – W.F. Jul 21 '16 at 07:19
  • 1
    Undefined behaviour is undefined. – Jesper Juhl Jul 21 '16 at 07:20
  • 1
    Size and has been set to zero, but capacity has not been changed. The allocated storage is likely still there, waiting to be reused. – user4581301 Jul 21 '16 at 07:21
  • 2
    you can find the anwser from here: http://stackoverflow.com/questions/17286271/why-doesnt-vectorclear-remove-elements-from-a-vector – user3113626 Jul 21 '16 at 07:21
  • Welcome to undefined behavior land! Try setting samples[9] and it should throw a memory access violation error. – Hame Jul 21 '16 at 07:21
  • 2
    @Hame I wouldn't count on that. What if the memory block assigned to the vector's data store is large enough to contain, say, 16 elements? or the some other variable in the program already owns the storage at samples[9]. – user4581301 Jul 21 '16 at 07:23
  • 1
    Also, don't miss this hilarious explanation http://stackoverflow.com/a/6445794/597607 – Bo Persson Jul 21 '16 at 07:27

2 Answers2

5

it seems it doesn't mean "default/empty" values.

Yes, it's just UB.

Note std::vector::operator[] doesn't perform bounds checking, while std::vector::at() does, and an exception of type std::out_of_range will be thrown for the case.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • clear() only sets the internal size value to 0. Because the vector class is reserving more memory than its actual size, to allow for push_back() without reallocation, the memory previously used by your vector before the clear() is keeped as reserved: that's why the operator[] don't throw an exception. But as mentionned by songyuanyao, you can use at() to perfom a check on the argument – rocambille Jul 21 '16 at 07:27
  • @wasthishelpful "that's why the operator[] don't throw an exception." This might be misleading, `std::vector::operator[]` just won't throw exceptions (for this). – songyuanyao Jul 21 '16 at 07:40
  • You're right ^^ I was speaking for this particular point only – rocambille Jul 21 '16 at 07:47
2

C++ is different from other languages like Java, C# or Python that many things are defined as undefined behavior instead of producing an error, especially things were detecting them would have a runtime cost associated. Checking out-of-bound accesses for arrays is such an example. Being undefined behavior, this also gives the compiler a great degree of freedom to optimize your code.

In you specific case, an out-of-bound access via std::vector::operator[] is undefined behavior. The compiler is free to generate any behavior it wants. The common case is just to perform the access to the memory position and return what is there.

Jens
  • 9,058
  • 2
  • 26
  • 43