C++: замена векторов и аннулирование указателя?

Кажется, у меня проблема с заменой элементов двух векторов. У меня есть два вектора, x и y, которые содержат объекты типа myclass. myclass имеет только одного публичного члена w. Я создаю вектор указателей, указывающих на члены w из x, а затем меняю местами векторы x и y. Я бы ожидал, что вектор указателей по-прежнему будет указывать на w членов x, но, похоже, это не так.

Вот тривиальный пример, чтобы воспроизвести мою проблему.

#include <iostream>
#include <vector>

using namespace std;

struct myclass
{
    double w;
};


int main()
{
    vector<myclass> x(10);
    for(int i=0; i!=10; i++) x[i].w = i;
    for(auto el : x) std::cout << el.w << std::endl; /* prints i */
    std::cout << std::endl;

    vector<double *> px(10);
    for(int i=0; i!=10; i++) px[i] = &x[i].w;
    for(auto el : px) std::cout << *el << std::endl; /* prints i */
    std::cout << std::endl;

    vector<myclass> y(10);
    for(int i=0; i!=10; i++) y[i].w = 2*i;
    for(auto el : y) std::cout << el.w << std::endl; /* prints 2*i */
    std::cout << std::endl;

    y.swap(x);

    for(auto &el : x) std::cout << &el.w << " " << el.w << std::endl; /* prints 2*i as it should */
    std::cout << std::endl;

    for(auto &el : px) std::cout << el << " " << *el << std::endl; /* should print 2*i, but prints i */
    std::cout << std::endl;
}

Обратите внимание, что элементы x и y поменялись местами, но px по-прежнему указывает на старые элементы. Я читал, что использование swap не должно аннулировать указатели/итераторы. Это правильно или я что-то упускаю? Заранее спасибо!


person linuxfever    schedule 27.12.2012    source источник
comment
Документы говорят, что они не будут признаны недействительными, и они не были - это означает, что они по-прежнему указывают на то, на что всегда указывали.   -  person JasonD    schedule 28.12.2012


Ответы (1)


Указатели и итераторы не становятся недействительными, но они следуют за содержимым контейнера.

Содержимое x заменяется на y, но итераторы и указатели на эти значения будут продолжать указывать на них (даже если они теперь находятся в y).

Подумайте об этом, как это могло бы работать по-другому? Если поменять местами два контейнера разной длины, на что будут указывать указатели на элементы в конце более длинного контейнера в более коротком контейнере? Как можно было бы реализовать swap() в O(1), если бы элементы каждого контейнера приходилось перемещать в памяти, чтобы указатели оставались действительными?

person Mankarse    schedule 28.12.2012