Почему я могу получить доступ к элементу, который я только что удалил из вектора stl в c ++? - PullRequest
1 голос
/ 23 марта 2011

В этом примере я создаю вектор с одним целым числом, а затем стираю это целое из вектора. Размер вектора уменьшается, но целое число все еще там! Почему целое число все еще там? Как может вектор размером 0 содержать элементы?

#include <vector>
#include <iostream>

using namespace std;

int main(int agrc, char* argv[])
{
    vector<int> v;
    v.push_back(450);

    cout << "Before" << endl;
    cout << "Size: " << v.size() << endl;
    cout << "First element: " << (*v.begin()) << endl;
    v.erase(v.begin());
    cout << "After" << endl;
    cout << "Size: " << v.size() << endl;
    cout << "First element: " << *(v.begin()) << endl;

    return(0);
}

выход:

Before
Size: 1
First element: 450
After
Size: 0
First element: 450

Ответы [ 5 ]

10 голосов
/ 23 марта 2011

Вы вызываете неопределенное поведение, разыменовывая неверную ячейку памяти. Обычно менеджер кучи не сразу освобождает удаленную память, используя delete в целях эффективности. Однако это не означает, что вы можете получить доступ к этой ячейке памяти, менеджер кучи может использовать эту ячейку памяти для других целей в любое время. Таким образом, ваша программа будет вести себя непредсказуемо, если вы разыменуете неверную ячейку памяти.

3 голосов
/ 23 марта 2011

IIRC вектор не освобождает пробел без специального указания, поэтому вы видите элемент, который все еще находится в его памяти, но не отслеживается вектором.Это одна из причин, по которой вы должны сначала проверить размер (другая причина в том, что если вы никогда ничего не назначали, вы будете разыменовывать указатель мусора).

1 голос
/ 23 марта 2011

Для начала, не рассчитывайте, что так будет во всех системах.То, как вектор работает внутри, зависит от реализации полностью .Разыменовывая неверную ячейку памяти, вы обходите поведение, описанное в документации.Другими словами, вы можете только рассчитывать на поведение, описанное в документах STL.

Причина, по которой вы все еще можете получить доступ к этой области памяти, заключается в том, что конкретная реализация, которую вы используете,не сразу удаляет память, но хранит ее некоторое время (возможно, в целях производительности).Другая реализация может очень хорошо удалить эту память немедленно, если этого пожелает автор.

0 голосов
/ 23 марта 2011

Какие у вас параметры компилятора?Я получаю сбой с обычными опциями, с обоими компиляторами, которые я регулярно использую (g ++ и VC ++).В случае g ++ вы должны установить некоторые дополнительные параметры (-D_GLIBCXX_DEBUG, я думаю) для этого поведения;насколько я могу судить, это по умолчанию для VC ++.(Моя команда для VC ++ была просто "cl / EHs bounds.cc".)

Как уже говорили другие, это неопределенное поведение, но с хорошим компилятором оно будет определено, чтобы вызвать сбой программы.1003 *

0 голосов
/ 23 марта 2011

Просто вектор не освободил память, но сохранил ее для будущего использования.

Это то, что мы называем "неопределенным поведением". Нет гарантии, что он будет работать в следующий раз, и этоможет легко вывести программу из строя в будущем.Не делай этого.

...