2

Why is this statement:

cout << values[0] << " " << values[1] << " " << values[2] << endl;

Showing

1 2 3

Even though pop back was used to remove the last element from the vector. Shouldn't the values be removed too? Or does the vector resize even though the element is removed?

Here is the sample code:

// This program demonstrates the vector pop_back member function.
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    vector<int> values;

    // Store values in the vector.
    values.push_back(1); // Last element in values is 1
    values.push_back(2); // Now elements in values are 1,2
    values.push_back(3); // Now elements in values are 1,2,3

    cout << "The size of values is " << values.size() << endl; // values has 3 elements

    // Remove a value from the vector.
    cout << "Popping a value from the vector...\n";
    values.pop_back();
    cout << "The size of values is now " << values.size() << endl; // 1 is Removed thus size is 2
    cout << values[0] << " " << values[1] << " " << values[2] << endl;

    // Now remove another value from the vector.
    cout << "Popping a value from the vector...\n";
    values.pop_back();
    cout << "The size of values is now " << values.size() << endl;
    cout << values[0] << " " << values[1] << " " << values[2] << endl;


    // Remove the last value from the vector.
    cout << "Popping a value from the vector...\n";
    values.pop_back();
    cout << "The size of values is now " << values.size() << endl;
    cout << values[0] << " " << values[1] << " " << values[2] << endl;

    return 0;

}
Dante
  • 537
  • 2
  • 4
  • 18
  • 6
    C++ vectors do not do bounds checking if you use `operator[]`. If you use the `at` function instead, you will get an out of range exception in the above code. The above code is instead just buggy, with no diagnostic required. – Chris Beck Sep 15 '15 at 04:14
  • 1
    When pop_back() is called element at the back is removed, that is, the destructor of the stored object is called, and length of the vector is removed by 1. If the container's capacity is not reduced, then you can still access the previous memory location. For the case of type int, you may still see the old value (in general this is undefined). – 911 Sep 15 '15 at 04:19

2 Answers2

8

"values" and "elements" are the same thing. pop_back() removes the last value from the vector, if the vector is not empty.

vector is designed so that it is the programmer's responsibility to not access out of bounds of the vector. If a vector has 2 elements and you try to access the third element via any method except for at(), you cause undefined behaviour.

To get bounds checking, use values.at(0) instead of values[0], etc., and include a try...catch block to catch the resulting exception.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
2

Even though pop back was used to remove the last element from the vector. Shouldn't the values be removed too?

What do you expect the value to be? 0? Garbage?

Or does the vector resize even though the element is removed?

Yes. The destructor for the object is called and the size (which is just the distance between _M_start and _M_finish, it's an ad-hoc stack basically) of the vector is reduced by one, as shown in this implementation:

void
pop_back()
{
    --this->_M_impl._M_finish;
    this->_M_impl.destroy(this->_M_impl._M_finish);
}

destroy eventually leads to a function that calls the destructor for the object pointed to by the pointer. From there on, you could reason what the value of an object after its lifetime has ended is: but then you'd be wasting your time. There's no point in reasoning once you've reached undefined behavior.


Here's what operator[] looks like:

reference
operator[](size_type __n)
{ return *(this->_M_impl._M_start + __n); }

You can see why this is bad if _M_start + __n > _M_finish.