C ++印刷shared_ptr的树使用count

问题描述 投票:1回答:3

我有麻烦()为我的共享指针工作了为什么当我打印以不同的方式在树上,我得到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)
c++ shared-ptr
3个回答
2
投票

这是因为你用std::make_shared<Node>(*this)其创建*thisone),这将复制this->childone->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


1
投票

当你调用Print(ptr),它作为共享指针引用传递,没有副本。

当你调用Print(),它使共享指针的拷贝,并传递,为Print(ptr)

这是该副本是加大了引用计数。如果你不希望这样的事情发生,不进行复印。您应该能够直接传递this作为参考。


1
投票

正如在其他的答案中提到,通过调用std::make_shared<Node>(*this)你实际上是在调用默认的拷贝构造函数。因此击打某处newObj->child = (*this).child(I,E - 重载=(赋值运算符),用于在std :: shared_ptr的),从而递增引用计数为2。当功能Print()退出,shared_ptr的被破坏,从而降低了ref计数到1 。

当您参考打电话,没有什么是创造,因此你看到预期的结果。

解决这个问题的一种方法是超载函数接受const Node &,然后你可以使用*this

© www.soinside.com 2019 - 2024. All rights reserved.