C++ shared_from_this() 不会让 obj 被破坏

Posted

技术标签:

【中文标题】C++ shared_from_this() 不会让 obj 被破坏【英文标题】:C++ shared_from_this() is not letting obj get destructed 【发布时间】:2021-11-23 12:33:09 【问题描述】:

我有以下一段代码,它正在创建一个简单的 Name 对象,并在其中创建另一个对象 Name,并带有 shared_from_this() 引用。当我从这里阅读 https://en.cppreference.com/w/cpp/memory/enable_shared_from_this/shared_from_this

“有效地执行 std::shared_ptr(weak_this),其中 weak_this 是 enable_shared_from_this 的私有可变 std::weak_ptr 成员。”

我理解为 shared_from_this() 只是创建一个指向共享 obj 的弱指针。但我不认为这是运行时的情况。有效地创建了一个循环引用。

最后,我期待 Name obj 应该被破坏,但这不是因为引用计数器是 2。

有人可以帮我理解我应该如何使用enable_shared_from_this(),它可以有效地清理名称 obj,一旦它失去参考。

#include <iostream>
#include <memory>
#include <string>
#include <chrono>
#include <thread>

using namespace std;

struct Another;
struct Name : public std::enable_shared_from_this<Name> 
    std::string t;
    int m, n, p;
    shared_ptr<Another> ann;
    Name() 
        std::cout << "constructor\n";
    
    void MakeSomething() 
        ann = std::make_shared<Another>(shared_from_this());
    
    ~Name() 
        std::cout << "destructor\n";
    
;

struct Another 
    shared_ptr<Name> nn;
    Another(shared_ptr<Name> n) : nn(n) 
        std::cout << "from another constructor " << nn.use_count() << "\n";
    
    ~Another() 
        std::cout << "from another destructor\n";
    
;

int main()

    
        auto n = std::make_shared<Name>();
        std::cout << "Name ref count so far: " << n.use_count() << "\n";

        auto p = n.get();
        //delete p;
        std::cout << "Name ref count so far: " << n.use_count() << "\n";

        n->MakeSomething();
        std::cout << "Name ref count so far: " << n.use_count() << "\n";
        
            shared_ptr<Name> m = n;
            std::cout << "Name ref count so far: " << n.use_count() << "\n";
        

        std::cout << "Name ref count so far: " << n.use_count() << "\n";
    
    // problem: at this point Name obj, should go out of reference and destructor to be called, which is NOT happening

    return 0;

这是运行时输出(编译器使用 msvc)

constructor
Name ref count so far: 1
Name ref count so far: 1
from another constructor 3
Name ref count so far: 2
Name ref count so far: 3
Name ref count so far: 2

【问题讨论】:

你有一个 shared_ptrs 的循环引用。它们永远不会超出范围,因为它们相互指向。 @Yksisarvinen 是的,我知道。 shared_from_this 正在创建循环引用,当在文档中说它正在创建弱引用时。正确的使用方式应该是什么shared_from_this 您可能需要让其中一个使用 std::weak_ptr shared_from_this无关。你有两个shared_ptrs,都指向对方。他们无法自行释放,因为任何一方都没有结束生命的时刻。您需要手动释放 (reset()) 其中一个来打破圈子。或者其中之一不能是shared_ptr,而是weak_ptr 或原始的、非拥有的指针。 "shared_from_this 正在创建循环引用" -- 不,是 创建了循环引用。如果函数shared_from_this 被单独调用(未分配给某物),它会返回一个立即销毁的临时对象。它需要您的 annnn 成员来创建循环引用。 shared_from_this 所做的只是简化创建循环引用的代码;它不是该代码的重要组成部分。 【参考方案1】:

我理解为 shared_from_this() 只是创建一个指向共享 obj 的弱指针。但我不认为这是运行时的情况。有效地创建了一个循环引用。

shared_from_this() 正在创建一个 weak_ptr,您将其传递给一个 shared_ptr 构造函数,由 (11) here 指定。该构造函数为同一个对象创建了一个shared_ptr,从而增加了引用计数。

还请记住,weak_ptr 根本不会影响引用计数,因此它不会影响您对引用计数的混淆。关注shared_ptrs 正在做什么。

【讨论】:

以上是关于C++ shared_from_this() 不会让 obj 被破坏的主要内容,如果未能解决你的问题,请参考以下文章

在 lambda 函数中使用 auto self(shared_from_this()) 变量的原因是啥?

shared_from_this使用boost :: asio抛出bad_weak_ptr

为什么调用shared_from_this调用std :: terminate

使用 shared_from_this 参数等待 std::future 获取 std::async 会阻止对 this 的破坏

shared_from_this()如何在派生类中工作,该派生类继承自从enabled_shared_from_this继承的基类

智能指针shared_ptr新特性shared_from_this及weak_ptr