Проблема с удалением unique_ptr из вектора - PullRequest
0 голосов
/ 09 июня 2019

Я борюсь с удалением unique_ptr из вектора. У меня есть вектор:

std::vector<std::unique_ptr<Agent>>;

, который я заполняю определенным количеством Агентов. Я делаю это следующим образом:

В списке конструкторов классов:

agentsVec(std::accumulate(agentsQuantity.begin(), agentsQuantity.end(), 0, 
                           [](int value, const QuantityMap::value_type& p) { return value + p.second; }))

А в функции, отвечающей за генерацию агентов:

auto agentVecIter = agentsVec.begin();
    std::for_each(agentsQuantity.begin(), agentsQuantity.end(), [this, &agentVecIter](const QuantityMap::value_type& p)
    {
        std::generate_n(agentVecIter, p.second, [this, &p]()
        {
            auto agent = factory.createAgent(p.first);
            changeAgentOnLattice(generatePosition(), agent->getID());
            return agent;
        });
        std::advance(agentVecIter, p.second);
    });

agentsQuantity - это карта, которая обозначает количество агентов определенного типа. Фабрика агентов возвращает std :: unique_ptr;

Во время выполнения программы может возникнуть необходимость в удалении какого-либо агента из вектора на основе его идентификатора (идентификатор агента затем возвращается в стек freeID).

Агент убийства:

std::experimental::erase_if(agentsVec, [this, &positionID](auto const& agent) { 
    auto agentID = agent->getID();
    if (positionID == agentID) {
        Utils::addIDToStack(agentID);
        return true;
    }
    return false;
});

Чтобы проверить это, я добавил 5 агентов, которые будут "убиты". Примерно в 40% случаев я получил:

Ошибка отладочного подтверждения! Итератор вектора не разыменовывается

Что я делаю не так?

РЕДАКТИРОВАТЬ: больше кода для уточнения. Решетка агентов (которая содержит agentVec) создается в классе Environment. Затем среда вступает в бесконечный цикл и перебирает все позиции в решетке и проверяет, существует ли там что-нибудь Если да -> он перемещает агента и обновляет его здоровье:

Окружающая среда :: Обновление работоспособности:

for (int i = 0; i < latticeSize; i++) {
    for (int j = 0; j < latticeSize; j++) {
        if (lattice->getAgentID(Position(i, j))) {
            Agent* currentAgent = lattice->getAgentInstance(Position(i, j));
            currentAgent->updateHealth();
            if (currentAgent->getAgentType() == Enums::AgentType::Predator && currentAgent->getHealth() <= -10) {
                lattice->killAgent(Position(i, j));
            }
        }
    }
}

Решетка :: Перемещение агента:

const auto originRow = Utils::BoundaryCondition(origin.first, latticeSize);
    const auto originCol = Utils::BoundaryCondition(origin.second, latticeSize);
    const auto destRow = Utils::BoundaryCondition(destination.first, latticeSize);
    const auto destCol = Utils::BoundaryCondition(destination.second, latticeSize);

    if (getAgentID(origin) == static_cast<int>(Enums::AgentType::Field)) {
        Logger::getInstance().Log("lattice", "\tCannot move - there is no moving creature on origin position");
        return false;
    }

    if (getAgentID(destination) != static_cast<int>(Enums::AgentType::Field)) {
        Logger::getInstance().Log("lattice", "\tCannot move - destination position is occupied");
        return false;
    }

    latticeMap[destRow][destCol] = static_cast<int>(getAgentID(origin));
    latticeMap[originRow][originCol] = static_cast<int>(Enums::AgentType::Field);
    Logger::getInstance().Log("lattice", "\tMoved succesfully");

    return true;

Получение агента (используется в Среде для получения указателя агента из Lattice :: agentsVec)

Agent* Lattice::getAgentInstance(Position position) {
    int ID = getAgentID(position);
    auto it = std::find_if(std::execution::par, agentsVec.begin(), agentsVec.end(),
        [=](std::unique_ptr<Agent>& agent) { return agent->getID() == ID; });
    if (it != agentsVec.end()) {
        return it->get();
    }
    return nullptr;
}

И получатель AgentType:

Enums::AgentType Lattice::checkAgentType(int ID)
{
    auto it = std::find_if(std::execution::par, agentsVec.begin(), agentsVec.end(), 
    [=](std::unique_ptr<Agent>& agent)  { return agent->getID() == ID; });

    if(it != agentsVec.end()) {
        return it->get()->getAgentType();
    }
    return Enums::AgentType::Unknown;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...