Использование std :: vector объектов указателя. Есть ли способ удалить элемент из вектора, когда он выходит из области видимости? - PullRequest
2 голосов
/ 03 апреля 2020

Я делаю мысленный переход от старой школы C ++ к " modern ".

У меня есть фабрика классов, которая используется для проверки всех экземпляров определенного класса, foo, поддерживаются в списке. Этот список используется для обработки всех foo с по порядку.

Это устаревшая система, которая использует обычные старые указатели (new / delete), но я думал о том, чтобы превратить их в shared_ptr s.

Буду ли я все еще нуждаться в вызове "RemoveMeFromList()" в деструкторе foo или есть какие-то волхвы c, о которых я не знаю?

Ответы [ 4 ]

2 голосов
/ 03 апреля 2020

В этом случае я предлагаю вам сохранить вектор слабых указателей (std::weak_ptr) на вашей фабрике:

std::vector<std::weak_ptr<foo>> foo_instances;

Теперь, с этим вектором, если один указатель выходит из области видимости , это будет истек. Таким образом, вы можете удалить просроченные указатели при следующей обработке вектора. Другими словами, вам не нужен явный метод «RemoveMeFromList», но вы можете сделать удаление указателей с истекшим сроком действия, когда вы go для обработки экземпляров foo.

1 голос
/ 03 апреля 2020

Вы можете реализовать решение с помощью shared_ptr и weak_ptr, как подсказывает eerorika, выполнив что-то подобное. Вы можете предпочесть это решение уникальному_ptr, если не хотите, чтобы Фабрика была владельцем объектов, определяющих , когда вещи недопустимы.

Ваш класс фабрики может выглядеть примерно так:

class Factory {
   public:
      std::shared_ptr<MyObject> create();
      std::vector<std::weak_ptr<MyObject>>& getObjects();
   private:
      std::vector<std::weak_ptr<MyObject>> objects;
      void cullInvalidObjects();
};

Мы просто создаем слабый_птр из shared_ptr объекта в методе фабрики:

std::shared_ptr<MyObject> Factory::create()
{
   auto object = std::make_shared<MyObject>();
   std::weak_ptr<MyObject> weakObject = object;
   objects.push_back(weakObject);
   return object;
};

Фабрика может иметь внутренний метод, который отбирает недопустимые объекты:

void Factory::cullInvalidObjects()
{
    auto iter = objects.begin();
    while (iter != objects.end())
    {
        if ((*iter).expired())
        {
            objects.erase(iter++);
        }
    }
}

и затем, когда вы заставляете объекты работать с ними, вы, вероятно, захотите отбросить список, прежде чем предоставлять его:

std::vector<std::weak_ptr<MyObject>>& Factory::getObjects()
{
   cullInvalidObjects()
   return objects;
}

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

void callSomeMethod(std::vector<std::weak_ptr<MyObject>>& objects)
{
   for (auto wObj : objects)
   {
       auto sObj = wObj.lock();
       if(p)
       {
         p->someMethod();
       }
   }
}
1 голос
/ 03 апреля 2020

Это в устаревшей системе, которая использует обычные старые указатели (новые / удалить), но я думал о том, чтобы превратить их в shared_ptr s.

Вы на самом деле не предоставили нам с включенным go, но я подозреваю, что std::shared_ptr не то, что вам нужно. std::shared_ptr используется для «совместного управления» владением всеми копиями указателя и уничтожения его, когда его нет. Такое убийство не уведомит ваш «фабричный» или центральный репозиторий о foo с. Но так как у вас действительно есть это, и вы хотите, чтобы оно отслеживало экземпляры, просто позвольте это быть тем, кто владеет ими. Самое большее, у вас могут быть сущности, которые получают указатели / ссылки на экземпляры foo, вместо этого получают оболочки, которые каким-то образом обрабатывают просто пересчет. Ваш центральный репозиторий foo будет обрабатывать удаления - если они вообще необходимы. Он может перерабатывать неиспользованные foo s - переинициализировать их и раздавать вместо того, чтобы выделять что-то новое.

Опять же, извините за довольно расплывчатый и абстрактный ответ.

1 голос
/ 03 апреля 2020

Буду ли я все еще нуждаться в вызове "RemoveMeFromList" в деструкторе foo

Да.

или есть волхвы c Я не в курсе?

Нет.

Можно реализовать пользовательский контейнер, который хранит слабые указатели на объекты, находящиеся в совместном владении, и при каждом доступе проверять, действителен ли указатель по-прежнему , Я не знаю, будет ли это хорошим дизайном для вас (кажется сомнительным).

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