📜  std::enable_shared_from_this 包括 (1)

📅  最后修改于: 2023-12-03 15:05:22.239000             🧑  作者: Mango

介绍 std::enable_shared_from_this

std::enable_shared_from_this 是 C++11 中的一个模板类,它提供了一种通过 std::shared_ptr 来获取 this 指针的方法。

背景

在 C++ 中,我们可以用如下方法构造一个智能指针:

auto ptr = std::make_shared<MyClass>();

但是,当我们在类内部想要获取该对象的智能指针时,通常需要这样做:

class MyClass {
public:
    std::shared_ptr<MyClass> getSharedPtr() {
        return std::shared_ptr<MyClass>(this);
    }
};

这样的写法存在一个问题:如果我们在 getSharedPtr() 中返回一个 std::shared_ptr,然后在外部将其传递给另一个 std::shared_ptr,就会出现引用计数错误。这是因为 std::shared_ptr 的计数器是针对一个特定的对象,而 getSharedPtr() 返回的是 this 指针,没有增加计数器。

如果我们希望在类内部安全地使用一个指向该对象的 std::shared_ptr,该怎么办呢?这就是 std::enable_shared_from_this 出现的背景。

使用方法

使用 std::enable_shared_from_this 可以让一个类在内部安全地获取一个指向该对象的 std::shared_ptr。具体的做法是:

  1. 继承 std::enable_shared_from_this
  2. 在对象被构造前,通过 std::shared_ptr 构造该对象。
class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::shared_ptr<MyClass> getSharedPtr() {
        return shared_from_this();
    }
};

需要注意的是,使用 shared_from_this() 时,该对象必须已经使用 std::shared_ptr 构造过了。

示例
#include <iostream>
#include <memory>

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    MyClass() {
        std::cout << "Constructing MyClass\n";
    }
    
    ~MyClass() {
        std::cout << "Destructing MyClass\n";
    }
    
    std::shared_ptr<MyClass> getSharedPtr() {
        return shared_from_this();
    }
};

int main() {
    std::shared_ptr<MyClass> ptr1(new MyClass);
    std::shared_ptr<MyClass> ptr2 = ptr1->getSharedPtr();
    
    std::cout << "ptr1.use_count() = " << ptr1.use_count() << '\n';
    std::cout << "ptr2.use_count() = " << ptr2.use_count() << '\n';
    
    return 0;
}

输出:

Constructing MyClass
ptr1.use_count() = 2
ptr2.use_count() = 2
Destructing MyClass
总结

使用 std::enable_shared_from_this 可以更加安全地获取一个指向该对象的 std::shared_ptr,避免了使用裸指针的不稳定性。需要注意的是,使用 shared_from_this() 时,对象必须已经使用 std::shared_ptr 构造过了。