尽管有pop(),如何避免删除priority_queue :: top()?

时间:2013-03-30 01:54:18

标签: c++ memory-management reference segmentation-fault priority-queue

STL和优先级优先级队列的接口包括

T const &   top () const;
void    pop ();

后者删除顶部元素。但是如果我想在pop()之后继续使用该元素,我想避免复制呢?例如,假设我有priority_queue<T> pq。我想写

const T& first = pq.top();      
pq.pop();
const T& second = pq.top();
analyze(second);
analyze(first);      // first *after* second

不幸的是,只要我弹出(),第一个引用就变为无效,所以我得到一个段错误。

我更喜欢像java nextElement()这样的解决方案,它返回top()并执行pop(),但只有当它超出范围时才会删除该元素。这样我就不需要跟踪pop()和什么时候了。但是,使用priority_queue<shared_pointer<T> >似乎没有帮助,因为将引用转换为shared_pointer不会增加其use_count。

如果重要,我更倾向于使用boost::fibonacci_heap来提高效率push()

任何想法或指示?谢谢!

3 个答案:

答案 0 :(得分:0)

您是否可以使用支持std :: move?

的编译器
int main()
{       
    std::priority_queue<std::string> str_q;
    str_q.push("aaa");
    str_q.push("bbb");
    str_q.push("ccc");
    std::string strs[3];

    strs[0] = std::move(const_cast<std::string&>(str_q.top()));
    std::cout<<str_q.top()<<std::endl;
    str_q.pop();
    strs[1] = std::move(const_cast<std::string&>(str_q.top()));
    std::cout<<str_q.top()<<std::endl;
    str_q.pop();
    strs[2] = std::move(const_cast<std::string&>(str_q.top()));
    std::cout<<str_q.top()<<std::endl;
    str_q.pop();

    for(auto const &data : strs){
        std::cout<<data<<std::endl;
    }            

    return 0;
}

编辑答案,因为返回类型是std :: string const&amp;,它无法移动 至少我们抛弃了常量。

答案 1 :(得分:0)

如果您愿意承担增加use count的费用,那么就我所知,boost::shared_ptrstd::shared_ptr都会这样做:

#include <iostream>
#include <vector>
#include <memory>
#include <queue>
#include <boost/shared_ptr.hpp>

template< typename T >
struct deref_less
{
  //typedef std::shared_ptr<T> P;
  typedef boost::shared_ptr<T> P;
  bool operator()( const P& lhs, const P& rhs ) { return *lhs < *rhs; }
};

int main()
{
   //std::priority_queue< std::shared_ptr<int>, std::vector< std::shared_ptr<int> >, deref_less< int >  > pq ;
   std::priority_queue< boost::shared_ptr<int>, std::vector< boost::shared_ptr<int> >, deref_less< int >  > pq ;

    boost::shared_ptr<int>
      sp1( new int(10)),
      sp2( new int(11)),
      sp3( new int(3))
      ;

      pq.push(sp1) ;
      pq.push(sp2) ;
      pq.push(sp3) ;

      std::cout << *pq.top() << std::endl ;

      std::cout << sp2.use_count() <<std::endl ;

      //std::shared_ptr<int> sp4( pq.top() ) ;
      boost::shared_ptr<int> sp4( pq.top() ) ;

      std::cout << sp2.use_count() <<std::endl ;

      pq.pop() ;

      std::cout << sp2.use_count() <<std::endl ;
      std::cout << *sp4 << std::endl ;
}

在线std版本here

答案 2 :(得分:0)

使用fibonacci_heap,您可以使用有序迭代器并将元素保留在堆中,直到完成为止。

auto it = heap.ordered_begin();
const T& first = *it;  // picking up ref to first element
const T& second = *++it;  // and to second element
analyze(first, second);
heap.pop();  // and now drop them
heap.pop();