Почему здесь не просто удаляется нулевой элемент вектора, а еще и заменяется значение второго?

Почему в данном коде, после строки v.erase(v.begin()); не просто удаляется нулевой элемент вектора, а еще и заменяется значение второго.

class A
{
public:
    int* p;

    A() : p() {}

    A(int _) : p(new int(_)) {}

    A(const A& a) {
        p = new int(*a.p);
    }

    virtual ~A() {
        delete p;
    }
};

void dump(const A& a)
{
    std::cout << *a.p << std::endl;
}

int main()
{
    std::vector<A> v;
    v.push_back(A(1));
    v.push_back(A(2));
    v.push_back(A(3));
    
    v.erase(v.begin());

    std::for_each(v.begin(), v.end(), dump);

    
    std::cin.get();
    return 0;
}

Вывод

2
-2054136144

Ответы (2 шт):

Автор решения: Harry

Представим себе строй солдат - значений в векторе.

Ррррассчитайсь!

Первый-второй-третий-...

Первого враги выводят и расстреливают. Ну, или начальство награждает и демобилизует. Неважно! Важно, что в строю его больше нет...

Ррррассчитайсь!

Первый-второй-третий-...

И кто теперь крикнет "первый"?

Только вот строй такой, что никто не умеет правильно делать шаг влево :) - нет оператора присваивания... Вот они при попытке сомкнуть строй просто падают. А поскольку освобождение места в строю сопровождается освобождением памяти - то проблемы поверхностного копирования становятся слишком глубокими :)

Вопросов больше нет?

Допишите в класс вот такой оператор -

A& operator=(const A& a) {
    cout << "===\n";
    delete p;
    p = new int(*a.p);
    return *this;
}

(вывод - чтоб вы видели, когда он вызывается) и посмотрите на результат.

→ Ссылка
Автор решения: Fat-Zer

Вообще говоря, для поддержки всех операций вектор требует, чтобы тип был как CopyConstructable, так и CopyAssignable, т.е. в нём применяется operator=(), а т.к. ты нарушил правило трёх, то operator=() по умолчанию делает глупость просто копируя указатель. Надо просто явно его определить:

A& operator=(const A& a) {
    delete p;
    p = new int(*a.p);
    return *this;        
}
→ Ссылка