• c++11 智能指针-辅助类 (std::enable_shared_from_this)


    定义于头文件 
    template< class T > class enable_shared_from_this; (C++11 起) 

    std::enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。

    若一个类 T 继承 std::enable_shared_from_this ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr 对象,它与 pt 共享 t 的所有权。

    构造函数

    std::enable_shared_from_this<T>::enable_shared_from_this

    constexpr enable_shared_from_this() noexcept;

    (1)(C++11 起)

    enable_shared_from_this( const enable_shared_from_this&obj ) noexcept;

    (2)(C++11 起)

    构造新的 enable_shared_from_this 对象。值初始化私有 std::weak_ptr 成员。

    参数

    obj-要复制的 enable_shared_from_this

    注意

    无移动构造函数:从导出自 shared_from_this 的对象移动不转移其共享身份。

    调用示例

    1. #include <iostream>
    2. #include <memory>
    3. struct Foo : public std::enable_shared_from_this<Foo>
    4. {
    5. Foo() {} // 隐式调用 enable_shared_from_this 构造函数
    6. std::shared_ptr<Foo> getFoo()
    7. {
    8. return shared_from_this();
    9. }
    10. };
    11. int main()
    12. {
    13. std::shared_ptr<Foo> pf1(new Foo);
    14. std::shared_ptr<Foo> pf2 = pf1->getFoo(); //pf1 共享对象所有权
    15. std::cout << "pf2.use_count() " << pf2.use_count() << std::endl;
    16. {
    17. pf2.reset();
    18. std::cout << "pf2.use_count() " << pf2.use_count() << std::endl;
    19. }
    20. }

     输出

    析构函数 

    std::enable_shared_from_this<T>::~enable_shared_from_this
    ~enable_shared_from_this();

    销毁 *this 。

    返回到 this 的引用

    std::enable_shared_from_this<T>::operator=
    1. enable_shared_from_this<T>& operator=
    2. ( const enable_shared_from_this<T> &obj ) noexcept;(C++11 起)

    不做任何事;返回 *this 。

    参数

    obj-赋值给 *this 的 enable_shared_from_this

    返回值

    *this

    注意

    私有的 std::weak_ptr 成员不受此赋值运算符影响。

    示例

    注意:定义 enable_shared_from_this::operator= 为受保护以避免意外切片,但允许导出类拥有默认的赋值运算符。

    调用示例

    1. #include <memory>
    2. #include <iostream>
    3. class SharedInt : public std::enable_shared_from_this<SharedInt>
    4. {
    5. public:
    6. explicit SharedInt(int n) : mNumber(n) {}
    7. SharedInt(const SharedInt&) = default;
    8. SharedInt(SharedInt&&) = default;
    9. ~SharedInt() = default;
    10. // 两个赋值运算符都使用 enable_shared_from_this::operator=
    11. SharedInt& operator=(const SharedInt&) = default;
    12. SharedInt& operator=(SharedInt&&) = default;
    13. int number() const
    14. {
    15. return mNumber;
    16. }
    17. private:
    18. int mNumber;
    19. };
    20. int main()
    21. {
    22. std::shared_ptr<SharedInt> a = std::make_shared<SharedInt>(2);
    23. std::shared_ptr<SharedInt> b = std::make_shared<SharedInt>(4);
    24. *a = *b;
    25. std::cout << a->number() << std::endl;
    26. }

    返回共享 *this 所有权的 shared_ptr

    std::enable_shared_from_this<T>::shared_from_this

    shared_ptr shared_from_this();

    (1)

    shared_ptr shared_from_this() const;

    (2)

    返回与所有指代 *this 的 std::shared_ptr 共享 *this 所有权的 std::shared_ptr

    等效地执行 std::shared_ptr(weak_this) ,其中 weak_thisenable_shared_from_this 的私有 mutable std::weak_ptr 成员。

    注意

    只容许在先前共享的对象,即 std::shared_ptr 所管理的对象上调用 shared_from_this 。(特别是不能在构造 *this 期间 shared_from_this 。)

    否则行为未定义 (C++17 前)抛出 std::bad_weak_ptr (由参数为默认构造的 weak_this 的 shared_ptr 构造函数) (C++17 起)。

    返回值

    与之前存在的 std::shared_ptr 共享 *this 所有权的 std::shared_ptr

    调用示例

    1. #include <iostream>
    2. #include <memory>
    3. struct Foo : public std::enable_shared_from_this<Foo>
    4. {
    5. Foo()
    6. {
    7. std::cout << "Foo::Foo\n";
    8. }
    9. ~Foo()
    10. {
    11. std::cout << "Foo::~Foo\n";
    12. }
    13. std::shared_ptr<Foo> getFoo()
    14. {
    15. return shared_from_this();
    16. }
    17. };
    18. int main()
    19. {
    20. Foo *f = new Foo;
    21. std::shared_ptr<Foo> pf1;
    22. {
    23. std::shared_ptr<Foo> pf2(f);
    24. pf1 = pf2->getFoo(); //pf2 的对象共享所有权
    25. }
    26. std::cout << "pf2 is gone\n";
    27. }

    注意

    enable_shared_from_this 的常见实现为:其内部保存着一个对 this 的弱引用(例如 std::weak_ptr )。 std::shared_ptr 的构造函数检测无歧义且可访问的 (C++17 起) enable_shared_from_this 基类,并且若内部存储的弱引用未为生存的 std::shared_ptr 占有,则 (C++17 起)赋值新建的 std::shared_ptr 为内部存储的弱引用。为已为另一 std::shared_ptr 所管理的对象构造一个 std::shared_ptr ,将不会考虑内部存储的弱引用,从而将导致未定义行为。

    只允许在先前已被std::shared_ptr 管理的对象上调用 shared_from_this 。否则调用行为未定义 (C++17 前)抛出 std::bad_weak_ptr 异常(通过 shared_ptr 从默认构造的 weak_this 的构造函数) (C++17 起)。

    enable_shared_from_this 提供安全的替用方案,以替代 std::shared_ptr(this) 这样的表达式(这种不安全的表达式可能会导致 this 被多个互不知晓的所有者析构,见下方示例)。

    调用示例

    1. #include <memory>
    2. #include <iostream>
    3. struct Good: std::enable_shared_from_this<Good> // 注意:继承
    4. {
    5. std::shared_ptr<Good> getptr()
    6. {
    7. return shared_from_this();
    8. }
    9. };
    10. struct Bad
    11. {
    12. // 错误写法:用不安全的表达式试图获得 this 的 shared_ptr 对象
    13. std::shared_ptr<Bad> getptr()
    14. {
    15. return std::shared_ptr<Bad>(this);
    16. }
    17. ~Bad()
    18. {
    19. std::cout << "Bad::~Bad() called\n";
    20. }
    21. };
    22. int main()
    23. {
    24. // 正确的示例:两个 shared_ptr 对象将会共享同一对象
    25. std::shared_ptr<Good> gp1 = std::make_shared<Good>();
    26. std::shared_ptr<Good> gp2 = gp1->getptr();
    27. std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
    28. // 错误的使用示例:调用 shared_from_this 但其没有被 std::shared_ptr 占有
    29. try
    30. {
    31. Good not_so_good;
    32. std::shared_ptr<Good> gp1 = not_so_good.getptr();
    33. }
    34. catch (std::bad_weak_ptr& e)
    35. {
    36. // C++17 前为未定义行为; C++17 起抛出 std::bad_weak_ptr 异常
    37. std::cout << e.what() << '\n';
    38. }
    39. // 错误的示例,每个 shared_ptr 都认为自己是对象仅有的所有者
    40. std::shared_ptr<Bad> bp1 = std::make_shared<Bad>();
    41. std::shared_ptr<Bad> bp2 = bp1->getptr();
    42. std::cout << "bp2.use_count() = " << bp2.use_count() << '\n';
    43. } // UB : Bad 对象将会被删除两次

    输出

  • 相关阅读:
    redis 中的八大问题
    用go实现一个循环队列
    移动零(力扣热题HOT100 之 力扣283)java
    STM32 从0开始系统学习2
    Python 音频处理工具库之pydub使用详解
    【3d游戏开发】使用Babylonjs+Vue3搭建属于我们的小岛
    计算机保研复习
    使用Loadrunner进行性能测试
    kube-scheduler addAllEventHandlers
    RabbitMQ中的死信队列产生的几个条件和应用场景
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/126797399