微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

从指针向量,2D指针数组中删除对象,并在一个循环中释放其内存

如何解决从指针向量,2D指针数组中删除对象,并在一个循环中释放其内存

在我的应用程序中,我有一个2D 环境,其中可以包含 Agent 对象。为了简化计算,我的环境由两个数据结构组成:

  1. Agent*** grid代表2D指针网格(如果座席在某个位置,则有一个指向它的指针,否则为nullptr)。
  2. 一个std::vector<Agent*> agents代表环境中的代理列表。当需要更新代理时,我使用此数据结构来防止遍历整个网格。

每次更新整个环境时,我都希望根据一个标准从环境中删除部分代理。因此,我想从上面描述的两个数据结构中删除代理,然后释放代理内存。另外,为了最大化效率,由于agents可能是一个很大的向量,因此我想在单个循环中执行remove和delete

以下是我的(也是不正确的)方法

void Environment::removeDeadAgents(){
std::vector<Agent*>::iterator it = agents.begin();

while(it != agents.end()){
    Agent* a = (*it);
    if(!a->isAlive()){
       grid[a->getY()][a->getX()] = nullptr;
       delete *it;
       it = agents.erase(it);
    }else{
        it++;
    }
}

我想念什么?

解决方法

您的方法可以重写,但使用std::stable_partition

可以更安全
#include <algorithm>

void Environment::removeDeadAgents()
{
   // partition the vector,alive to the left of the partition,// dead to the right of the partition.  An iterator to the partitioning
   // point is returned.
   auto iter = std::stable_partition(agents.begin(),agents.end(),[](Agent *a) { return a->isAlive();});

   // null out all the dead ones in the grid and call delete.
   std::for_each(iter,[&](Agent* a) {grid[a->getY()][a->getX()] = nullptr; delete a;});

  // erase dead ones from vector.
  agents.erase(iter,agents.end());
}

正如评论所述,该分区只是移动指针,将活动代理放置在该分区的左侧,将死区放置在该分区的右侧。

然后在一个循环中,重置网格并在每个失效的网格上调用delete。 然后,在此过程的最后,只需完成一次对erase的调用,而不是像原始代码那样对erase进行多次调用。

此外,请注意,擦除操作是一次调用,并且擦除的唯一项目是vector尾部的项目(这就是为什么我在分区的右侧划分了死代理的原因)。从向量后面擦除项目比擦除向量中间或前面项目要有效得多。

如果agent向量中项目的顺序并不重要,则可以使用std::partition,这将比std::stable_partition更有效。 std::partition会简单地遍历向量,而无需保持原始顺序,而是将活动代理和死代理分别放在分区点的左侧和右侧。

如果您不了解std::partition,则可以通过一次遍历向量并进行策略性交换来对原始代码进行更好的实现,并将有生命的代理带到向量的前面,然后记录最后一个活动的代理被交换到的位置,然后从那里开始擦除(是的,这样做需要一些代码,但是您知道了)。本质上,这就是该解决方案(使用std::partitionstd::stable_partition)的作用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。