I have the following Container
class
template <typename T>
class Container
{
private:
std::vector<std::shared_ptr<T>> items_;
public:
void addItem(std::shared_ptr<T> item)
{
std::cout << "useCount addItem pre: " << item.use_count() << std::endl;
items_.push_back(std::move(item));
std::cout << "useCount addItem post: " << item.use_count() << std::endl;
}
};
and I'm calling it like this
int main(int argc, char** argv) {
std::unique_ptr<Container<std::string>> container = std::make_unique<Container<std::string>>();
std::shared_ptr<std::string> s = std::make_shared<std::string>("hello");
std::cout << "useCount main pre: " << s.use_count() << std::endl;
container->addItem(s);
std::cout << "useCount main post: " << s.use_count() << std::endl;
return 0;
}
This is the output I get
useCount main pre: 1
useCount addItem pre: 2
useCount addItem post: 0
useCount main post: 2
Line by line...
Makes sense, there's only one reference to s
as soon as its defined
Makes sense, s
gets copied into item
so its reference count is incremented by 1
I've given items_
ownership of item
, so the reference count shouldn't change since addItem
has relinquished ownership and transferred it to items_
. I expect the reference count to be 2, once from main
and once from items_
. Instead it's 0.
Makes sense as long as one reference is from main
and one reference is from items_
.
Thanks for any clarification!
std::move
moves the item out of that variable into another one. As one author put it, it "has explicit license to pillage [the variable]." For most std objects, that puts the original object into an unspecified state. However, it appears std:shared_ptr
is an exception in that it leaves the object in an empty state.
What all this boils down to is that you can't treat item
as the same reference to s
anymore after the move. It is in a different state, storing something else. That's why your reference count is off.
If instead you had done this:
std::cout << "useCount addItem post: " << items_.back().use_count() << std::endl;
You would have got the expected output of 2
.
After a shared pointer has been moved from, it shall be empty. The use count of an empty shared pointer is 0.
From another point of view, you were expecting that at that point, main
, and items_
owned the object (which is correct), but if they are counted in the use_count
of the pointer item
, then that would be a total of three shared pointers owning the object. That contradicts with your expectation of 2. Of course, this is explained by the fact that item
no longer owns the object, so its use count is actually no longer related to other pointers that do own it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With