lexpexkex (lexpexkex) wrote,
lexpexkex
lexpexkex

Categories:

C++. Списки указателей и прочие весёлые "ну его нахер".

В общем, С++ кажется понятным только на видеоуроках, а шаг вправо, шаг влево вызывают сразу мучительные вопросы, основной из которых "как же так?".

Вот есть у меня список указателей на объекты.

[Spoiler (click to open)]
  1. #include <iostream>
  2. #include <list>
  3. #include <string>
  4. #include <list>
  5. using namespace std;
  6.  
  7. class Base
  8. {public:
  9. int x = 0;
  10. Base() {}
  11. Base(int x) { this->x = x; }
  12. virtual void doit() { cout << x << " Base!\n"; }
  13. virtual ~Base() { cout << x << " deleted...\n"; }
  14. };
  15.  
  16. class Derived : public Base
  17. {public:
  18. Derived()
  19. { x = 1; }
  20. void doit() override { cout <<x<< " Derived!\n"; }
  21. };
  22.  
  23.  
  24. int main(int argc, const char * argv[])
  25. {
  26. list<unique_ptr<Base>> v;
  27.  
  28.  
  29. v.emplace_back(new Base(1));
  30. v.emplace_back(new Base(1));
  31. //v.emplace_back(new Derived);
  32. v.emplace_back(new Base(1));
  33. v.emplace_back(new Base(1));
  34. v.emplace_back(new Base(1));
  35. //v.emplace_back(new Derived);
  36. v.emplace_back(new Base(0));
  37.  
  38.  
  39. for (auto it = v.begin(); it != v.end(); ++it)
  40. {
  41.  
  42. if ((*it)->x == 1)
  43. {
  44. it=v.erase(it); //it=v.begin();
  45. }
  46. }
  47. //for (auto& o : v) { o->doit(); }
  48. for (auto it = v.begin(); it != v.end(); ++it)
  49. {
  50. (*it)->doit();
  51. }
  52.  
  53. system("pause");
  54. }


И я хочу пройтись по нему итератором и удалить объекты, которые мне не нужны по какому-то признаку.
Ну ладно, вылетает если я удаляю последний объект. Хотя написано, что функция erase возвращает нужный итератор, который я тут же и присваиваю текущему. А дальше, в теории, должна быть проверка, не последний ли он.
Но это мелочи. Если два объекта соотвествуют условию, по которому я их хочу грохнуть и идут подряд, то грохнется только один. Даже если я присвою текущему итератору it=v.begin()(это закомментировано, но расскоментирование не даёт эффекта), то есть как бы перезапущу цикл заново и вернусь в начало, один хрен они останутся не удалены. Я ж, вроде, запускаю всё сначала, где предидущих удалённых объектов уже нет, следовательно они не идут подряд! Что мешает их удалить?
И как мне поместить в таком списке указателей его объекты в другой? Так не работает
[Spoiler (click to open)]
list<unique_ptr<Base>> v;
list<unique_ptr<Base>> v1;
	for (auto it = v.begin(); it != v.end(); ++it)
	{
 
		v1.emplace_back(*it);
	}
 
	for (auto it = v1.begin(); it != v1.end(); ++it)
	{
		(*it)->doit();
	}


А как надо-то?

И ещё один вопрос. В С# всё также замучено насчёт итерирования по списку, которое работает как-то по особому?
ЗЫ. Первоначальной задачей было поместить в один список объекты разных классов, один из которых базовый, другой наследник.
ЗЫ. Теперь стыдно. Вполне мог догадаться, что erase возвращает значение на следующий элемент и идёт пропуск. Я ж и жаловался, что пропускает и удаляет не всё!
Tags: #include
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

  • 40 comments