带有priority_queue.top()的std :: move()

时间:2018-03-08 03:40:42

标签: c++ c++11 shared-ptr move

我是智能指针的新手。最近我开始进行一些并行仿真,我认为shared_ptr将有助于防止内存泄漏。我听说增加实例数会导致不可忽视的额外时间开销,所以我希望避免这样做。

在我的代码中,我使用priority_queue来管理模拟中的事件。为了确保我理解在这些容器中shared_ptr会发生什么,我做了一些测试:

std::priority_queue<std::shared_ptr<Base>> queue;
queue.push(std::make_shared<Derived>());
std::shared_ptr<Base> p = queue.top();
//std::shared_ptr<Base> p = std::move(queue.top());

std::cout << "Created a shared Derived (as a pointer to Base)\n"
          << "  p.get() = " << p.get()
          << ", p.use_count() = " << p.use_count() << '\n';

使用以上两种不同的方式从priority_queue获取指针,我期待第二种方式在use_count()中返回1。但是我看到值为2,无论我是否使用std::move()来获取队列中的顶部指针。我用g++ -std=c++0x [FileName]

编译

有人可以指出我做错了吗?上述两种方法都表明我还有额外的时间吗?

4 个答案:

答案 0 :(得分:4)

priority_queue::top会将const&返回到顶部元素。

std::shared_ptr<Base> p = queue.top();

上面的一行会创建一个新的shared_ptr,现在与shared_ptr中的priority_queue共享top元素的所有权,因此use_count为2

std::move不会影响结果,因为moving a const object会调用shared_ptr复制构造函数,与上面的行相同。

要将use_count保持为1,请使用

std::shared_ptr<Base> const& p = queue.top();

答案 1 :(得分:1)

这应该给你use_count为1。

const std::shared_ptr<Base>& p = queue.top();

而且,这应该给你use_count为2。

std::shared_ptr<Base> p = queue.top();

_

#include <iostream>
#include <memory>
#include <queue>

using namespace std;

class Base
{
    public:

    Base() {}

    virtual void print()
    {
        cout << "Base" << endl;
    }
};

class Derived
:
    public Base
{
    public:
    Derived() {}

    void print()
    {
        cout << "Derived" << endl;
    }
};


int main()
{

  std::priority_queue<std::shared_ptr<Base>> queue;
  queue.push(std::make_shared<Derived>());
  const std::shared_ptr<Base>& p = queue.top();
  //std::shared_ptr<Base> p = std::move(queue.top());

  std::cout << "Created a shared Derived (as a pointer to Base)\n"
            << "  p.get() = " << p.get()
                      << ", p.use_count() = " << p.use_count() << '\n';

}

答案 2 :(得分:0)

queue.top()返回const_reference,const无法移动。由于不允许修改优先级队列中的元素,因此它会返回,它可以破坏优先级队列中的顺序。

答案 3 :(得分:0)

移动不会删除指向的对象。它使它处于一些有效但未指定的状态。&#34; (他们的话,不是我的。)或者至少如果Base和Derived遵守规则的话。如果不是Derived,你曾经使用过std :: strings,它们可能会被留作空字符串,但是实现将它们保留为&#34;是惊人的!搬出去了。&#34;。