2009-01-23 109 views
3

使用STL的priority_queue只要我尝试使用pop(),就会收到错误“invalid heap”。我可以将我的值推入队列,队列的top()是我期望和可访问的。 pop(),当它重新堆积时,似乎有问题。C++标准模板库优先级队列抛出带有消息“Invalid Heap”的异常

我正在存储指向队列中模板类的指针。我有重载的对比:

template <class type> 
class vertexPriorityCompare 
{ 
public: 
    bool operator()(Vertex<type>* leftVertex, Vertex<type>* rightVertex) const 
    { 
     if(leftVertex->getDistanceFromSource() < 0 && rightVertex->getDistanceFromSource() < 0) 
     { 
     return false; 
     } 
     else if(leftVertex->getDistanceFromSource() < 0) 
     { 
     return true; 
     } 
     else if(rightVertex->getDistanceFromSource() < 0) 
     { 
     return false; 
     } 
     else 
     { 
     return leftVertex->getDistanceFromSource() > rightVertex->getDistanceFromSource(); 
     } 
    } 
}; 

priority_queue是一类的私有成员:

priority_queue< Vertex<type>*, vector< Vertex<type>* >, vertexPriorityCompare<type> > Q; 

在它时尚的超负荷工作,因为负的距离被认为是无穷大,总是大于不管怎么说;为了表示无穷大,距离被初始化为-1。队列需要保持最小值,但非负值。

我解引用重载中的指针,是我在那里允许的吗?而且,是否还有另一个运营商需要超载?

我会附上代码,但看起来如果我这样做,它会吓跑人们。要求看更多,我会附加到另一条消息。

我动态地声明了一个指向指针的数组,这些是被推入的东西,因为我认为priority_queue是通过引用存储的,所以如果我只是把循环中声明的指针放入队列中,那么这个指针会超出范围。这些指针指向正确的Vertex<type>,并存在于整个函数中。

Visual Studio 2008中调试带我到“stdthrow.cpp”线路24

+0

请格式化您的代码 – cbrulak 2009-01-23 22:17:15

+0

Visual Studio调试器也应该为您提供一个调用堆栈。这可能也有帮助。 – MSN 2009-01-23 22:24:37

回答

0

你在哪里调用这个函数?

我的猜测是无效堆是一个指针,你从“this function caller's”代码传入函数。或者,当你从矢量中取出顶点时,你可能会走出界限。

我没有看到任何错误的功能。

请提供堆栈跟踪

0

没有调用堆栈,这将是一个有点难以确定的问题是什么,但你可能是没有正确地分配Vertex<...>,试图从堆栈中释放Vertex<...>,或不初始化Vertex<...>*为有效值。

3

这可能是你的比较功能。为了测试,用一个简单的版本,只是比较指针替换:

bool operator()(...) 
{ 
    return leftVertex<rightVertex; 
} 

如果问题不再出现,那么问题是你比较函数是无效的。您的比较器必须定义一个"strict-weak ordering"。我没有足够的人来证明它没有,但我敢打赌就是这样。

+1

+1“严格弱排序”的一部分表示,如果Compare(x,y)为true,则Compare(y,x)*必须为* false。如果两个距离值均为-1,则此功能不处理该情况。 – 2009-01-23 23:49:08

3

比较函数看起来不错,如果对象getDistanceFromSource()的值不会更改,而该对象在队列中。这是保证吗?或者是否可能对这些对象进行更改,影响getDistanceFromSource(),而这些更改是在队列中还是队列初始填充期间进行的?

0

这一点让我害怕:

我动态申报 指针数组的指针,这是什么意思 得到推,因为我引用假设 priority_queue店,所以 如果我只是把一个指针在 中声明循环进入队列,该指针 超出范围。这些指针 指向适当的顶点,并在整个函数中存在 。

你不清楚你是如何填充队列的。 您必须创建顶点对象,并且它们必须保留在内存中,并且在队列中的整个时间内返回相同的距离。

队列不通过引用存储,它存储副本 - 但在这种情况下,您所放入的是指针,因此它会复制指针,该指针仍将指向您分配的原始对象。

我想我们需要一个简短的完整例子才能得到更多。