Почему указатели на переменные в векторе остаются действительными?

#c #pointers #vector

#c #указатели #вектор

Вопрос:

Возьмем, к примеру, этот код:

 int a = 1;
int b = 2;
int c = 3;
std::vector<int> myVector;
myVector.push_back(a);
myVector.push_back(b);
myVector.push_back(c);
int * b_pointer;
b_pointer = amp;myVector[1]
 

По моему опыту b_pointer , всегда будет указывать на b , даже если вектор может перераспределяться, что должно привести к тому b_pointer , что он будет указывать на ненужные данные. Есть ли когда-нибудь ситуация, в которой это не сработает?

Комментарии:

1. b_pointer не указывает на b , он указывает на второй элемент, хранящийся в my_vector .

2. @Капитан Очевидный, если бы я позвонил myVector.erase(myVector.begin()) , был бы b_pointer still действителен?

3. Iterator/pointer/reference invalidation это то, что вы ищете. .push_back() аннулирует указатели, если происходит перераспределение.

4. Вы ошибаетесь в своем предположении, что указатель «остается действительным». На самом деле вы имеете в виду, что указатель, похоже, работает, несмотря на то, что он недействителен.

5. Вероятно, начальная емкость вектора больше 3, так что, скорее всего, перераспределения не будет. Пожалуйста, обратите внимание на «вероятно».

Ответ №1:

По сути, вы спрашиваете, остается ли действительным итератор (хотя тип векторного итератора не обязательно совпадает с простым указателем)

В документации для std::vector<>::insert говорится

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

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

Комментарии:

1. С другой стороны, происходит перераспределение, при котором все векторные данные копируются в новое местоположение. Старое местоположение по-прежнему имеет то же значение , что и раньше, но это не гарантирует, что оно останется таким.

Ответ №2:

После myVector того, как произойдет перераспределение внутреннего буфера, b_pointer будет указывать на недопустимую память, просто и ясно. Разыменование приведет к неопределенному поведению.

Однако очень возможно, что память, на которую он указывает, все еще содержит данные, которые он хранил ранее; зачем кому-то платить за то, чтобы каким-то образом ее уничтожить? В любом случае, никто по закону не может получить к нему доступ. Если за это время произойдет достаточное выделение средств, оно в конечном итоге будет заменено чем-то другим.