Удаление из вектора
От: TTL Беларусь  
Дата: 14.01.04 19:35
Оценка:
Есть следующие классы:
class Base{}; — абстрактный базовый класс
class Child1:public Base{};
class Child2:public Base{};

и три вектора:
std::vector<Child1*> Ch1Vec;
std::vector<Child2*> Ch2Vec;
std::vector<Base*> BsVec; //содержит элементы из Сh1Vec и Ch2Vec

Где-то в программе:
std::vector <Child1*> :: iterator Ch1Itr; 
std::vector <Base*> :: iterator BsItr;
Ch1Itr = Ch1Vec.begin();
BsItr = BsVec.begin();
while (dynamic_cast<Child1*>(*BsItr) != *Ch1Itr)
  ++BsItr;
Base *delptr = *BsItr;
delete delptr;
BsVec.erase(BsItr);
Ch1Vec.erase(Ch1Itr);


Т.е. имея итератор Ch1Itr я удалил записи на объект Child1 из векторов BsVec и Ch1Vec.
Тоже самое могу сделать, если имею итератор Сh2Itr.

А вот как обратную процедуру, т.е. имея итератор BsItr удалить записи из BsVec и одного из
векторов, хранящего указатели на потомков?
Вообще-то как удалить понятно, как наиболее быстро определить из какого вектора потомков
надо удалять? Неужели придется делать проход по всем векторам потомков, пока не встречу
искомый элемент?
... << RSDN@Home 1.1 beta 2 >>
Re: Удаление из вектора
От: Bell Россия  
Дата: 15.01.04 09:55
Оценка: 2 (1)
Здравствуйте, TTL, Вы писали:

TTL>Есть следующие классы:

TTL>class Base{}; — абстрактный базовый класс
TTL>class Child1:public Base{};
TTL>class Child2:public Base{};

TTL>и три вектора:

TTL>std::vector<Child1*> Ch1Vec;
TTL>std::vector<Child2*> Ch2Vec;
TTL>std::vector<Base*> BsVec; //содержит элементы из Сh1Vec и Ch2Vec

TTL>Где-то в программе:

TTL>
TTL>std::vector <Child1*> :: iterator Ch1Itr; 
TTL>std::vector <Base*> :: iterator BsItr;
TTL>Ch1Itr = Ch1Vec.begin();
TTL>BsItr = BsVec.begin();
TTL>while (dynamic_cast<Child1*>(*BsItr) != *Ch1Itr)
TTL>  ++BsItr;
TTL>Base *delptr = *BsItr;
TTL>delete delptr;
TTL>BsVec.erase(BsItr);
TTL>Ch1Vec.erase(Ch1Itr);
TTL>


TTL>Т.е. имея итератор Ch1Itr я удалил записи на объект Child1 из векторов BsVec и Ch1Vec.

TTL>Тоже самое могу сделать, если имею итератор Сh2Itr.

TTL>А вот как обратную процедуру, т.е. имея итератор BsItr удалить записи из BsVec и одного из

TTL>векторов, хранящего указатели на потомков?
TTL>Вообще-то как удалить понятно, как наиболее быстро определить из какого вектора потомков
TTL>надо удалять? Неужели придется делать проход по всем векторам потомков, пока не встречу
TTL>искомый элемент?

ИМХО крайне неудачная реализация — использование dynamic_cast совершенно излишне:

std::vector <Child1*> :: iterator Ch1Itr; 
std::vector <Base*> :: iterator BsItr;
Ch1Itr = Ch1Vec.begin();
BsItr = std::find(BsVec.begin(), BsVec.end(), *Ch1Itr);


Обратная процедура практически ничем не отличается (за исключением того, что здесь использование dynamic_cast оправдано):

std::vector <Base*> :: iterator BsItr = BsVec.begin();
Child1* p1 = dynamic_cast<Child1*>(*BsItr);
if(p1)
{
   std::vector <Child1*> :: iterator Ch1Itr = std::find(Ch1Vec.begin(), Ch1Vec.end(), p1);
   ...
}
else
{
   std::vector <Child2*> :: iterator Ch2Itr = std::find(Ch2Vec.begin(), Ch2Vec.end(), static_cast<Child2*>(*BsItr));
   ...

}


ЗЫ
Почему используется std::vector, а не тот же std::set?
Любите книгу — источник знаний (с) М.Горький
Re: Удаление из вектора
От: Кодт Россия  
Дата: 15.01.04 10:28
Оценка: 2 (1)
Здравствуйте, TTL, Вы писали:
<>

Во-первых, не нужен dynamic_cast. Делай static_cast<Base*>(child).

Во-вторых, для поиска — задействуй std::find(...) | std::find_if(...).

В-третьих, множество одиночных erase дороже выполнения tail=remove_if(...), erase(tail, end()).

В-четвертых, если массивы отсортированы, то процедура становится линейной (хотя стандартные алгоритмы, скорее всего, уже не подойдут — придется все делать ручками). А сейчас она квадратичная.
Перекуём баги на фичи!
Re[2]: Удаление из вектора
От: TTL Беларусь  
Дата: 15.01.04 20:52
Оценка:
Спасибо, Bell.

B>Обратная процедура практически ничем не отличается (за исключением того, что здесь использование dynamic_cast оправдано):


B>
B>std::vector <Base*> :: iterator BsItr = BsVec.begin();
B>Child1* p1 = dynamic_cast<Child1*>(*BsItr);
B>if(p1)
B>{
B>   std::vector <Child1*> :: iterator Ch1Itr = std::find(Ch1Vec.begin(), Ch1Vec.end(), p1);
B>   ...
B>}
B>else
B>{
B>   std::vector <Child2*> :: iterator Ch2Itr = std::find(Ch2Vec.begin(), Ch2Vec.end(), static_cast<Child2*>(*BsItr));

Здесь тоже надо dynamic_cast? 

B>}
B>


B>ЗЫ

B>Почему используется std::vector, а не тот же std::set?

Использую обращение по индексу. Подходящей функции сравнения элементов нет.
Re[3]: Удаление из вектора
От: Bell Россия  
Дата: 16.01.04 07:33
Оценка:
Здравствуйте, TTL, Вы писали:

B>>Почему используется std::vector, а не тот же std::set?


TTL>Использую обращение по индексу.

Ок, весомый аргумент
TTL>Подходящей функции сравнения элементов нет.
Ну ты же указатели хранишь, а для них operator < уже есть.
Любите книгу — источник знаний (с) М.Горький
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.