zoukankan      html  css  js  c++  java
  • std::enable_shared_from_this使用

      玩过C++shared_ptr类型的智能指针的同学,是否有接触过std::enable_shared_from_this,它的出现为我们提供哪些编程方面的便利呢?下面就介绍它。

    一、std::enable_shared_from_this的作用

      按照enable_shared_from_this - C++ Reference (cplusplus.com)文档介绍:继承std::enable_shared_from_this的子类,可以使用shared_from_this成员函数获取自身的shared_ptr指针;该类提供了允许继承类的对象创建指向自身实例的shared_ptr,并且与存在shared_ptr对象共享所有权。什么意思呢?我们接下来通过代码进行介绍。

    二、如何使用std::enable_shared_from_this

      上面已经介绍了,需要定义一个继承类继承这个类,代码如下:

     1 namespace test_enable_shared_from_this{
     2 
     3     class Derived : public std::enable_shared_from_this<Derived>
     4     {
     5     public:
     6         void SetValue(int a)
     7         {
     8             _a = a;
     9         }
    10         int GetValue() const
    11         {
    12             return _a;
    13         }
    14     private:
    15         int _a;
    16     };
    17 
    18 }

      那怎么使用这个继承类呢?我们分别在栈,堆上创建对象,然后调用shared_from_this成员函数返回的对象是啥。

      在栈上使用对象:

    1 int main()
    2 {
    3     using namespace test_enable_shared_from_this;
    4     Derived d;
    5     auto obj = d.shared_from_this();
    6     
    7      return 0;  
    8 }

          

      在栈上创建的对象不能调用该函数,会导致异常抛出:bad_weak_ptr。其实我们可以通过shared_from_this成员函数返回的是shared_ptr就知道不行,那么对象只能在堆上创建。能否裸指针呢?

    1 int main()
    2 {
    3     using namespace test_enable_shared_from_this;
    4     auto d = new Derived;
    5     auto obj = d->shared_from_this();
    6     
    7     return 0;
    8 }

           

      直接在堆上创建对象也不行。我们只能使用智能指针std::shared_ptr和unique_ptr,其实大家应该早就知道是哪个了,这里做详细说明是为了对问题的各种情况都进行验证加深对其使用。接下来我们使用

    std::shared_ptr。

    1 int main()
    2 {
    3     using namespace test_enable_shared_from_this;
    4     auto d = std::shared_ptr<Derived>();
    5     auto obj = d->shared_from_this();
    6    
    7     return 0;
    8 }

           

      

      观察两个对象,完全一模一样。这就是文档上介绍std::enable_shared_from_this提供的一种机制。那我们试试std::unique_ptr:

    int main()
    {
        using namespace test_enable_shared_from_this;
        auto d = std::make_unique<Derived>();
        auto obj = d->shared_from_this();
    
        return 0;
    }

           

       也不行。其实上面三种行不通的方式返回的指针都是空的。如下:

           

      所以使用shared_from_this的继承类对象只能是std::shared_ptr,其他方式都不行,如果误用的话,会导致返回的对象为空而出现其他问题。

    三、std::enable_shared_from_this的继承问题

      我们上面只是继承一层,如果另外一个类继承上面的类,那能够正常使用shared_from_this函数吗?获取的对象是最后继承的吗?

      如下代码验证:

     1 namespace test_enable_shared_from_this{
     2 
     3     class Derived : public std::enable_shared_from_this<Derived>
     4     {
     5     public:
     6         void SetValue(int a)
     7         {
     8             _a = a;
     9         }
    10         int GetValue() const
    11         {
    12             return _a;
    13         }
    14     private:
    15         int _a;
    16     };
    17 
    18     class Derived1 : public Derived
    19     {
    20     private:
    21         int _b;
    22     };
    23 
    24 }

       调用代码如下:

    1 int main()
    2 {
    3     using namespace test_enable_shared_from_this;
    4     auto d1 = std::make_shared<Derived1>();
    5     auto obj = d1->shared_from_this();
    6    
    7     return 0;
    8 }

      

       发现问题没有?虽然d1和obj对象地址一样,但是对象内存包含的成员属性不同。d1有自身的属性成员变量,但是obj没有,只含有基类的属性成员变量。是不是shared_from_this返回的对象中只包含那些直接继承

    std::enable_shared_from_this呢?我们用多继承验证下:

     1 namespace test_enable_shared_from_this{
     2 
     3     class Derived : public std::enable_shared_from_this<Derived>
     4     {
     5     public:
     6         void SetValue(int a)
     7         {
     8             _a = a;
     9         }
    10         int GetValue() const
    11         {
    12             return _a;
    13         }
    14     private:
    15         int _a;
    16     };
    17 
    18     class Derived1 : public std::enable_shared_from_this<Derived1>
    19     {
    20     private:
    21         int _b;
    22     };
    23 
    24     class Derived2 : public Derived, public Derived1
    25     {
    26     private:
    27         int _c;
    28     };
    29 
    30 }
    1 int main()
    2 {
    3     using namespace test_enable_shared_from_this;
    4     auto d2 = std::make_shared<Derived2>();
    5     auto obj = d2->shared_from_this();
    6  
    7     return 0;
    8 }

           

       直接提示执行不明确,这个很好理解,它不知道你究竟返回哪个子类std::shared_ptr。所以,继承类中不能存在多次继承std::enable_shared_from_this。哪个类继承的这个类,就返回这个类实例化的对象。我一般在其他类对象需要共享该类对象的情况下使用,这样该类就直接通过shared_ptr共享自身对象,如果其他类是通过引用或裸指针的方式共享该类,就不会继承这个类。

  • 相关阅读:
    [Python] xrange和range的使用区别
    安装ipython notebook及基本命令(快捷键)
    Django model 反向引用中的related_name
    Django模板系统——过滤器
    介绍Git的17条基本用法
    Hive HBase 整合
    Hive的动态分区
    Hive中的数据库(Database)和表(Table)
    Hive中数据的加载和导出
    Hive入门--2.分区表 外部分区表 关联查询
  • 原文地址:https://www.cnblogs.com/smartNeo/p/14766607.html
Copyright © 2011-2022 走看看