Что происходит с указателями, когда векторам требуется больше памяти и переопределять память? - PullRequest
9 голосов
/ 24 ноября 2011

Когда вектору требуется больше памяти, он куда-то перераспределяет память, я пока не знаю, где!и затем указатели становятся недействительными, есть ли какое-нибудь хорошее объяснение этому?

Я имею в виду, куда они идут, что происходит с моими контейнерами?(не связанные списки)

Ответы [ 3 ]

16 голосов
/ 24 ноября 2011

Краткий ответ: Все будет хорошо.Не беспокойтесь об этом и вернитесь к работе.

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

std::vector<int> v = get_vector();

int & a = v[6];
int * b = &v[7];
std::vector<int>::iterator c = v.begin();
std::advance(it, 8);

v.resize(100);

Теперь a, b и c недопустимы: вы не можете использовать a и разыменование b или c.

Длинный ответ: Вектор отслеживает динамическую память.Когда память исчерпана, она выделяет новый, больший фрагмент в другом месте и копирует (или перемещает) все старые элементы поверх (а затем освобождает старую память, уничтожая старые объекты).Выделение и освобождение памяти осуществляется с помощью allocator (обычно std::allocator<T>), который, в свою очередь, обычно вызывает ::operator new() для извлечения памяти, который, в свою очередь, обычно вызывает malloc().Детали могут отличаться и зависеть от вашей платформы.В любом случае любые ранее удерживаемые ссылки, указатели или итераторы больше не действительны (предположительно, потому что они ссылаются на освободившуюся память, хотя в стандарте не указано, почему они недействительны).

5 голосов
/ 24 ноября 2011

Когда вы добавляете или удаляете элементы из vector, все итераторы (и указатели) на элементы внутри него становятся недействительными. Если вам нужно сохранить указатель на элемент в векторе, то создайте вектор const или используйте другой контейнер.

Вам не должно быть важно, где вектор хранит вещи. Вам не нужно ничего делать, просто дайте ему сделать свою работу.

4 голосов
/ 24 ноября 2011

Когда вы используете std::vector, класс заботится обо всех деталях, касающихся выделения памяти, указателей, изменения размера и т. Д.

Класс vector предоставляет свое содержимое через итераторы и ссылки.Мутации вектора потенциально могут сделать недействительными итераторы и ссылки, потому что может потребоваться перераспределение.

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

Если вы хотите сохранить ссылку на элемент в векторе и сделать эту ссылку действительной даже после мутации, вам следует запомнитьиндекс, а не указатель или ссылка на элемент.В этом случае совершенно безопасно добавить в конец вектора, а значение индекса по-прежнему ссылается на тот же элемент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...