Во-первых, это очень , скорее всего, ваша проблема разрешима, если в первую очередь не использовать динамическое распределение вручную. Есть причины, по которым вы можете использовать динамическое выделение (например, полиморфное хранилище), но даже в этом случае вам следует ориентироваться на интеллектуальные указатели, а не на выделение вручную.
Отключить указатели
Чтобы сделать это с регулярным вектором конкретных объектов (не указателей), вы просто
std::vector<Bullet> bulletVector;
Дополнения могут быть сделаны примерно так:
bulletVector.emplace_back(x,y,dirX,dirY,size,duration);
bulletVector.back().assignTexture(btext);
Удаление всех элементов на основе длительности, достигающей нуля, будет просто использовать удалить / стереть идиома, как это:
bulletVector.erase(std::remove_if(
bulletVector.begin(),
bulletVector.end(),
[](auto const& b) { return b.getDuration() == 0; }),
bulletVector.end());
Имейте в виду, что хотя этот метод хранения данных и является наиболее предпочтительным, он потребует изменений в остальной части кода. Везде, где вы сейчас делаете это:
bulletVector[i]->doSomething();
станет
bulletVector[i].doSomething();
Больше интеллектуальных указателей
Если вам нужно использовать динамическое размещение, не используйте указатели, управляемые вручную . Это рецепт утечки памяти и ответственности за владение, и если вы думаете, что с вами этого не случится, вы наивны. Скорее используйте умные указатели. Два основных шаблона интеллектуальных указателей: std::unique_ptr
и std::shared_ptr
. Также есть std::weak_ptr
, которые заслуживают похвального упоминания, поскольку в некоторых ситуациях это очень удобно (не ваша, как я могу сказать).
std::vector<std::shared_ptr<Bullet>> bulletVector;
Следовательно, дополнения могут быть выполнены следующим образом (при условии, что это сделано с учетом полиморфизма и может быть более одного типа пули, в данном случае MagicBullet
и SilverBullet
, оба получены из Bullet
):
std::shared_ptr<Bullet> bullet = std::make_shared<MagicBullet>(x,y,dirX,dirY,size,duration);
bullet->assignTexture(btext);
bulletVector.emplace_back(bullet);
bullet = std::make_shared<SilverBullet>(x,y,dirX,dirY,size,duration);
bullet->assignTexture(btext);
bulletVector.emplace_back(bullet);
или просто храните обычные патроны:
bullet = std::make_shared<Bullet>(x,y,dirX,dirY,size,duration);
bullet->assignTexture(btext);
bulletVector.emplace_back(bullet);
Алгоритм удаления идентичен, только функция предиката условия изменяется (и ненамного)
bulletVector.erase(std::remove_if(
bulletVector.begin(),
bulletVector.end(),
[](auto const& b) { return b->getDuration() == 0; }),
bulletVector.end());
Самая приятная часть этого кода - оставшаяся часть вашего кода, скорее всего, практически не потребует никаких изменений. Но я подчеркиваю, это реальная выгода only (за исключением очевидного, а именно, больше не нужно управлять памятью самостоятельно).
Учитывая выбор между двумя методами (вектор конкретных объектов против вектора умных указателей), выбирайте осторожно. Если первое работает, используйте его. Если это не так, либо подумайте о том, как он может работать, либо воспользуйтесь последним.
Но прежде всего прекратить управление памятью вручную .