Векторные итераторы - PullRequest
       10

Векторные итераторы

0 голосов
/ 13 сентября 2011

У меня есть следующий код.

vector<IRD>* irds = myotherobj->getIRDs();//gets a pointer to the vector<IRD>
for(vector<IRD>::iterator it = irds->begin(); it < irds->end(); it++)
    {
        IRD* ird = dynamic_cast<IRD*>(it);
        ird->doSomething();
        //this works (*it).doSomething();

    }

Это похоже на ошибку ... Я просто хочу получить указатель на каждый элемент в векторе без использования (* it).все кончено.

  1. Как получить указатель на объект?
  2. Когда я перебираю векторные указатели, что именно я перебираю?Это копия каждого элемента, или я работаю с реальным объектом в векторе, когда я говорю (* it) .doSomething (),

Ответы [ 7 ]

5 голосов
/ 13 сентября 2011

Почему вы хотите получить указатель?

Использовать ссылку:

for(vector<IRD>::iterator it = irds->begin(); it != irds->end(); ++it)
{
    IRD & ird = *it;
    ird.doSomething();
}

В качестве альтернативы:

for(vector<IRD>::iterator it = irds->begin(); it != irds->end(); ++it)
{
    it->doSomething();
}

Также, как все говорили, используйте != при сравнении итераторов, а не <. Хотя в этом случае это будет работать, оно перестанет работать, если вы используете другой контейнер (и для этого итераторы: абстрагирование основного контейнера).

2 голосов
/ 13 сентября 2011

Вам нужно использовать != с итераторами для проверки конца, а не <, как это было бы с указателями. operator< может работать с vector итераторами, но если вы переключите контейнеры (на такие, как list), ваш код больше не будет компилироваться, поэтому обычно лучше использовать !=.

Кроме того, итератор - это не тот тип, на который он указывает, поэтому не пытайтесь его приводить. Вы можете использовать перегруженные operator-> на итераторах.

vector<IRD>* irds = myotherobj->getIRDs();//gets a pointer to the vector<IRD>
for(vector<IRD>::iterator it = irds->begin(); it != irds->end(); ++it)
{
    it->dosomething();
}
1 голос
/ 13 сентября 2011

Сначала подумайте, нужен ли вам указатель на элемент или вы просто пытаетесь использовать итераторы, но избегаете их. Похоже, вы пытаетесь кодировать C на C ++, а не кодировать C ++. В приведенном вами примере кажется, что вместо преобразования в указатель и последующей работы с этим указателем, почему бы просто не использовать итератор напрямую? it->doSomething() вместо ird->doSomething().

Если вы думаете, что вам нужно сохранить этот указатель для последующего использования в векторе после некоторой работы, это потенциально опасно. Векторные итераторы и , указывающие на элементы в векторе, могут быть признаны недействительными, то есть они больше не указывают на вектор, поэтому вы в основном пытаетесь использовать память после ее освобождения, что опасно. Типичным примером того, что может сделать недействительным итератор, является добавление нового элемента. Я попал в беспорядок, пытаясь сохранить итератор, и проделал большую работу, чтобы попытаться заставить его работать, включая написание функции re_validate_iterator (). В конечном счете, мое решение оказалось очень запутанным и даже не работало во всех случаях, кроме того, что оно не масштабировалось.

Решением для сохранения положения вектора является сохранение его в виде смещения. Некоторое целое число, указывающее позицию в векторе, в котором находится ваш элемент. Затем вы можете получить к нему доступ либо с помощью myvector.begin() + index, если вам нужно работать с итераторами, либо с помощью myvector.at (index), если вам нужна ссылка на сам элемент с проверкой границ, или просто myvector [index], если вам не нужна проверка границ.

1 голос
/ 13 сентября 2011

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

vector<IRD>* irds = myotherobj->getIRDs();
for(vector<IRD>::iterator it = irds->begin(); it != irds->end(); ++it)
{
    IRD& ird = *it;
    ird.doSomething();
    // alternatively, it->doSomething();
}
0 голосов
/ 13 сентября 2011

Обычная идиома - это & ​​* it, чтобы получить указатель.Динамические приведения не имеют к этому никакого отношения.

0 голосов
/ 13 сентября 2011

Когда я перебираю иди по указателям вектора, что именно я перебираю?Это копия каждого элемента, или я работаю с реальным объектом в векторе, когда я говорю (* it) .doSomething (),

Когда вы перебираете вектор, вы работаете ссам объект, а не его копия.

0 голосов
/ 13 сентября 2011

Вы можете получить указатель от итератора, выполнив &*it. Вы получаете указатель на фактический IRD объект, хранящийся внутри вектора. Вы можете изменить объект с помощью указателя, и модификация будет «прилипать»: она будет сохраняться внутри вектора.

Однако, поскольку ваш вектор содержит реальные объекты (не указатели на объекты), я не вижу никакой точки в dynamic_cast. Тип указателя IRD * и указывает на IRD объект.

Единственный случай, когда разыменованный итератор может ссылаться на копию (или, точнее, на прокси-объект), это vector<bool>, который может быть реализован как битовый вектор.

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