【问题标题】:advice on memory management when using STL priority_queue使用 STL priority_queue 时有关内存管理的建议
【发布时间】:2012-10-14 08:28:45
【问题描述】:

我正在尝试从 Java 适应 C++,但当我从 STL priority_queue 中 pop() 一个项目时,我不确定管理内存的正确方法。

我是否应该使用 delete 来清理从队列中删除的不再需要的项目?如果是这样,怎么做?如果没有,为什么不呢?

我自己写了一个小程序来学习如何使用priority_queue(代码如下)。在这个程序中,内存泄漏没什么大不了的,因为它的规模很小,而且结束得很快。但是我想学习正确的做事方式,这样我就可以编写一个正确处理更大队列而不会发生内存泄漏的程序。

我不明白的是:top() 返回的是引用而不是指针。但是我不能在引用上使用 delete,可以吗?

有人可以在这里指出正确的方向吗?

--------

struct PathCost{
    int dest;
    int cost;
    PathCost(int _dest, int _cost){
      dest = _dest;
      cost = _cost;
    }
    bool operator<(PathCost other) const;
    bool operator>(PathCost other) const;
};

bool PathCost::operator<(PathCost other) const{
  return cost < other.cost;
}
bool PathCost::operator>(PathCost other) const{
      return cost > other.cost;
}


int main(){

  PathCost pc = PathCost(1, 2);
  pc = PathCost(3, 4);
  PathCost* pcp = new PathCost(5, 6);
  delete pcp;

  priority_queue<PathCost,
                 vector<PathCost>,
                 greater<vector<PathCost>::value_type> > tentativeQ;

  cout << "loading priority queue ...\n";
  tentativeQ.push(PathCost(8, 88));
  tentativeQ.push(PathCost(5, 55));
  tentativeQ.push(PathCost(7, 77));
  tentativeQ.push(PathCost(4, 44));

  cout << "\nlist items on queue in priority order ...\n";
  while (!tentativeQ.empty()){
    pc = tentativeQ.top();
    cout << "dest:" << pc.dest << " cost:" << pc.cost << endl;
    tentativeQ.pop();
    /* DO I NEED TO DO MEMORY CLEANUP AT THIS POINT? */
  }
}

【问题讨论】:

  • 简而言之,没有。您的变量都是自动的。每次弹出都会从队列顶部删除一个项目并适当地销毁它。一般来说,如果你不newmalloc 某事,你不必担心deleteing 或freeing 它(strdup() 等无法承受)。
  • 谢谢。这很有帮助。我知道我有一些 Java 思维要忘掉。
  • 很高兴它有帮助。 Juanchopanza 的答案是正确的,顺便说一句,如果你对它感到满意,应该这样标记。 (旁边的绿色小勾号)。

标签: c++ memory-leaks stl priority-queue


【解决方案1】:

我是否应该使用 delete 来清理从队列中删除的不再需要的项目?如果是这样,怎么做?如果没有,为什么不呢?

您不需要执行任何清理,因为priority_queue 持有PathCost 对象。当它们从队列中移除时,会根据语言规则自动调用它们的析构函数。

在幕后,故事可能要复杂一些。通常,将项目插入priority_queue 数据结构将导致动态分配该对象的副本。但是资源分配和解除分配由底层数据结构(默认std::vector)负责,因此您不必担心内存管理。据说标准库容器和容器适配器具有值语义

我不明白的是:top() 返回的是引用而不是指针。但是我不能在引用上使用 delete,可以吗?

priority_queue 据说拥有它所拥有的元素,所以如果你引用其中一个元素,你就不能删除它。实际上,您根本不知道它是否需要删除。此外,尽管您可以访问队列中元素的引用,但您不必保留对这些元素的引用。您也可以制作自己的副本:

const PathCost& pRef = tentativeQ.top(); // take constant reference to top element
PathCost p = tentativeQ.top(); // make copy of last element

在第一种情况下,您必须注意不要在通过调用 pop() 删除顶部元素后使用该引用。

【讨论】:

  • 感谢您的详细回复 - 非常有帮助。
  • 所以只是为了检查我的理解是否正确......如果我这样做'tentativeQ.push(PathCost(5, 55));'循环内的操作(​​当然,每次都有不同的值 - 从文件中读取),然后在本地分配在循环结束时超出范围的自动变量,但 priority_queue 将创建自己的每个副本一,只保留这些副本,直到它们被 pop()ped,此时priority_queue 将自己清理它制作的副本。我在正确的轨道上吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 2019-11-24
相关资源
最近更新 更多