我有麻烦()为我的共享指针工作了为什么当我打印以不同的方式在树上,我得到use_counts的不同的号码。
使用下面的代码,当我打电话的方法“单>打印()”,我似乎获得错误裁判2为一个立即的孩子,但是当使用“单>打印(之一)”我得到了正确的号码参考文献,这是1。
我怎么可以改变我的代码,以便“单>打印()”返回树中的所有节点正确的引用数?
#include <iostream>
#include <memory>
template<class T> using sp = std::shared_ptr<T>;
struct Node {
int value;
sp<Node> child;
Node(int value): value {value} {}
inline void Print() const {
Print(std::make_shared<Node>(*this));
}
inline void Print(const sp<Node>& ptr) const {
Print(ptr, "", false);
}
void Print(const sp<Node>& ptr, const std::string& prepend, bool isEnd) const {
if(ptr != nullptr) {
std::cout << prepend << (isEnd ? "└────" : "├────");
std::cout << " " << ptr->value << " (" << ptr.use_count() << ")" << std::endl;
} else {
std::cout << " " << ptr->value << std::endl;
}
if(ptr->child != nullptr) {
Print(ptr->child, prepend + (isEnd ? " " : "│ "), false);
}
}
};
int main(int argc, char * argv[])
{
sp<Node> one = std::make_shared<Node>(1);
one->child = std::make_shared<Node>(2);
one->child->child = std::make_shared<Node>(3);
one->child->child->child = std::make_shared<Node>(4);
one->child->child->child = std::make_shared<Node>(5);
one->Print();
one->Print(one);
return 0;
}
输出看起来像:
单>打印();
├──── 1 (1)
│ └──── 2 (2)
│ └──── 3 (1)
│ └──── 5 (1)
单>打印(之一);
├──── 1 (1)
│ └──── 2 (1)
│ └──── 3 (1)
│ └──── 5 (1)
这是因为你用std::make_shared<Node>(*this)
其创建*this
(one
),这将复制this->child
(one->chile
)的副本,并增加引用计数器。
你想要的是大概从enable_shared_from_this
继承和使用shared_from_this
,那么你会得到
├──── 1 (2)
│ └──── 2 (1)
│ └──── 3 (1)
│ └──── 5 (1)
更重要的是,如果你不需要引用计数器(通常如此),你并不需要一个智能指针,如果你不打算来管理资源,你可以简单地接受Node*
。其实,你可以使用this
并丢弃所有的指针在这个例子中。
示例代码。 (使用this
代替ptr
)
struct Node: std::enable_shared_from_this<Node> {
int value;
sp<Node> child;
Node(int value): value {value} {}
void Print() const {
Print("", false);
}
void Print(const std::string& prepend, bool isEnd) const {
std::cout << prepend << (isEnd ? "└────" : "├────");
std::cout << " " << this->value << " (" << shared_from_this().use_count()-1 /*remove current count*/ << ")" << std::endl;
if(this->child) {
this->child->Print(prepend + (isEnd ? " " : "│ "), false);
}
}
};
您还可以使用week_from_this
(C ++ 17),wandbox example
当你调用Print(ptr)
,它作为共享指针引用传递,没有副本。
当你调用Print()
,它使共享指针的拷贝,并传递,为Print(ptr)
。
这是该副本是加大了引用计数。如果你不希望这样的事情发生,不进行复印。您应该能够直接传递this
作为参考。
正如在其他的答案中提到,通过调用std::make_shared<Node>(*this)
你实际上是在调用默认的拷贝构造函数。因此击打某处newObj->child = (*this).child
(I,E - 重载=(赋值运算符),用于在std :: shared_ptr的),从而递增引用计数为2。当功能Print()
退出,shared_ptr的被破坏,从而降低了ref计数到1 。
当您参考打电话,没有什么是创造,因此你看到预期的结果。
解决这个问题的一种方法是超载函数接受const Node &
,然后你可以使用*this
。