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