为什么`std :: priority_queue :: top()`无法返回非常量引用?

时间:2020-04-17 13:25:12

标签: c++ stl c++14 priority-queue

我需要维护大型对象(类型为Q)的优先级队列T。由于复制这些对象非常昂贵,因此我希望能够使用auto h = std::move(Q.top())检索可写对象。但由于std::priority_queue<std::unique_ptr<T>>::top()仅返回const引用,因此无法执行此操作。为什么? (有一个简单的解决方法吗?)

3 个答案:

答案 0 :(得分:1)

您可以将大型对象作为unique_ptr<T>存储在优先级队列中。需要注意的是queue.top()返回一个const unique_ptr<T>&,这意味着T本身不是 const。因此,您可以这样做:

T obj(std::move(*queue.top()));
queue.pop();

编辑:由于您的T没有move构造函数,因此,我只说一点,然后使用std::shared_ptr<T>

std::priority_queue<std::shared_ptr<T>, ...> queue;

// fill queue

// No need for anything special. 
std::shared_ptr<T> ptr = queue.top();
queue.pop();

答案 1 :(得分:0)

您可以将大对象包装到其他结构中,该结构将具有一个供自定义比较功能使用的字段,该成员不应受 move 操作的影响,例如,它应受某些普通数据的影响像mr={5px}这样的类型:

int
struct BigObject { std::unique_ptr<int> data; int forCmp; }; struct Cmp { bool operator()(const BigObject& lhs, const BigObject& rhs) { return lhs.forCmp < rhs.forCmp; } }; 队列内部顺序之后的

不能被破坏。已移动的BigObject实例仍具有比较器使用的有效值move(queue.top())

然后从forCmp继承,通过执行此操作,您将可以访问priority_queue底层容器,并添加c方法:

front

用途:

template<class T, class Cmp>
struct Wrapper : std::priority_queue<T,std::vector<T>,Cmp> {
    T& front() {
        return this->c.front();
    }
};

Full demo

答案 2 :(得分:0)

您可以继承priority_queue并写成T pop()来隐藏void pop()

template <typename T>
T fixed_priority_queue<T>::pop() {
    std::pop_heap(c.begin(), c.end(), comp); 
    T value = std::move(c.back());
    c.pop_back();
    return value;
}