Wrong destructor called by vector erase

Viewed 194

I have a vector with some objects. I noticed that when I remove one element from vector with erase method, I get the destructor call to the wrong element (always to the last element). Here a minimal example that produce a bad output.

// Example program
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Test {
    public:
        Test(string value) {
            _value = value;
            cout << "Constructor:" << _value << endl;
        }
        Test(const Test &t) {
            _value = t._value;
            cout << "Copied:" << _value << endl;
        }
        ~Test() {
            cout << "Destructor:" << _value << endl;
        }
        string print() {
            return _value;
        }
        string _value;
};

int main()
{
    vector<Test> vec;
    vec.reserve(3);
    cout << "Creation" << endl << endl;
    vec.push_back(Test("1"));
    vec.push_back(Test("2"));
    vec.push_back(Test("3"));

    cout << endl << "Deleting" << endl << endl;

    vec.erase(vec.begin());     // Here is called the element with value "3"
    vec.erase(vec.begin());     // Here is called the element with value "3"

    cout << endl << "Log" << endl << endl;

    // But the final log print "3"
    for (unsigned i = 0; i < vec.size(); i++) {
        cout << vec[i].print()<<endl;
    }

    return 0;
}

The output is:

Creation

Constructor:1
Copied:1
Destructor:1
Constructor:2
Copied:2
Destructor:2
Constructor:3
Copied:3
Destructor:3

Deleting

Destructor:3         <-- WRONG, NEED TO BE 1
Destructor:3         <-- WRONG, NEED TO BE 2

Log

3
Destructor:3

I would solve this problem without change the container vector.

1 Answers

vec.erase(vec.begin()); does not destruct the first element. It overwrites it by shifting all of the subsequent ones by one place, using either the move- or copy-assignment operator. What remains of the last element after it has been moved from is then destructed, which is what you're observing.

Related