Reputation: 21
I am new to smart pointers. Recently I started working on some parallel simulations and I thought shared_ptr
will help prevent memory leaks. I heard that incrementing the number of instances can cause non-negligible extra time overhead, so I hope to avoid doing that.
In my code I was using a priority_queue to manage the events in the simulation. To make sure I understood what happens with shared_ptr in these containers I did some tests:
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';
Using the above two different ways to get the pointer from the priority_queue
, I was expecting the second way to return 1 in use_count()
. However I saw a value of 2, whether or not I used std::move()
to get the top pointer in the queue. I compiled with g++ -std=c++0x [FileName]
Can someone point out where I was doing wrong? Do both the methods above indicate I will still have extra time over head?
Upvotes: 1
Views: 925
Reputation: 82
This should give you use_count of 1.
const std::shared_ptr<Base>& p = queue.top();
And, this should give you use_count of 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';
}
Upvotes: 1
Reputation: 109109
priority_queue::top
returns a const&
to the top element.
std::shared_ptr<Base> p = queue.top();
The line above creates a new shared_ptr
which now shares ownership of the top element with the shared_ptr
that's in the priority_queue
, so use_count
is 2.
std::move
doesn't affect the result because moving a const
object will call the shared_ptr
copy constructor, same as the line above.
To keep use_count
at 1, use
std::shared_ptr<Base> const& p = queue.top();
Upvotes: 4
Reputation: 17026
Move does not delete the object pointed to. It leaves it in some "valid but unspecified state." (Their words, not mine.) Or at least it will if Base and Derived play by the rules. If rather than Derived, you had used std::strings, they would probably be left as empty strings, but it would be legal for the implementation to leave them as "Surprise! Moved out.".
Upvotes: 0
Reputation: 38341
queue.top()
returns const_reference
, const can not be moved. Const returned since elements in a priority queue are not allowed to be modified, it can break an order in a priority queue.
Upvotes: 0