Предположим, у меня есть следующее:
struct Foo {
Foo () : bar(NULL), box(true) {}
Bar* bar;
bool box;
};
и я заявляю следующее:
std::vector<Foo> vec(3);
У меня есть функция, которая делает что-то вроде этого:
Foo& giveFoo() { //finds a certain foo and does return vec[i]; }
Затем вызывающий абонент передает адрес Foo
он получает по ссылке как Foo*
к другому парню. Что мне интересно, однако, если этот указатель на Foo
останется в силе после запуска вектора в vec
? Если существующий Foo
элементы в vec
затем копируются предположительно Foo*
что плавало теперь будет болтаться? Это так или нет? Я отлаживаю приложение, но не могу воспроизвести это.
Любые указатели или ссылки на элементы будут недействительными, когда вектор будет перераспределен, как и любые итераторы.
Указатель будет оставаться действительным до тех пор, пока вы не вызовете неконстантную функцию-член для вектора, которая:
заставляет его размер превышать его емкость (когда это произойдет, внутреннее хранилище будет
перераспределить и все указатели и ссылки на элементы будут признаны недействительными) или
вставляет элемент перед элементом, на который указывает указатель, или
удаляет элемент из вектора, или
удаляет элемент из вектора, который был расположен перед элементом, на который указывает указатель.
Первые две пули могут произойти одновременно. Разница в том, что ссылки / указатели на элементы, расположенные до точки вставки, остаются действительными, пока размер не превышает емкость.
Да, это может стать недействительным, потому что в основном, когда vector
нужно увеличить зарезервированный размер, он просто удаляет свое внутреннее хранилище (которое в основном является массивом), выделяет увеличенное и копирует туда свое предыдущее содержимое.
Если вы уверены, что этот индекс остается прежним, вы можете обращаться к нужным данным, используя этот индекс каждый раз, когда он вам нужен.
Ниже то, что стандарт говорит о валидности векторных итераторов для векторных модификаторов:
vector::push_back()
, vector::insert()
, vector::emplace_back()
, vector::emplace()
:
Вызывает перераспределение, если новый размер больше, чем старая емкость. Если перераспределение не происходит, все итераторы и ссылки до точки вставки остаются действительными.
vector::erase()
:
Делает недействительными итераторы и ссылки в или после точки удаления.
Любое предположение за пределами этого небезопасно.