[smart_ptr] shared_from_this

  如果你使用过回调函数的话,可能会发现,在注册回调(Callback)的时候,一般都会传递一个上下文(context)给Observable,Observable会在调用Callback的时候把Context传递给Callback。

  以libevent为例,使用event_new创建event时,要传递一个EventCallback,和一个void* 类型的context,前者libevent会在socket有事件(EV_READ EV_WRITE...)发生时调用,后者会在前者被调用的传递给他。

  代码示例大致 struct event* e = event_new(base,sockfd,EV_READ | EV_PERSIST, EventCallback,base);

  这里最后一个参数base作为context传给了event_new,当有事件发生时,这个base会被作为参数传给EventCallback,我们可能回这么用:

  void EventCallback(int sockfd,short waht,void* arg)
  {
    struct event_base* base = (struct event_base*)(arg);
    // ...
  }

 

 这是从用户的角度看,如果时从event_base的角度看:事件发生,调用用户注册的回调,传递 发生事件的句柄sockfd事件类型 what用户的Context。其中,除了用户的Context,还要给用户sockfdwhat。那么,如果要给用户的不是sockfd,而是一个指向event_base自己的指针呢?而且传递指针是唯一的办法。如何保证用户不把指针delete掉呢?

  C++的shared_ptr可以解决这个问题。这也代表event_base是被shared_ptr保护着的。

  那么,event_base如何获得指向自己的指针指针呢?

  创建一个吗?

  EventCallback(make_shared(this),EventType,Context);

  这样传递给EventCallback的shared_ptr和保护event_base的shared_ptr不共享引用计数,这样,不行。

  用一个全局变量保存 一个保护event_base的shared_ptr的引用,然后在需要的时候传这个引用。

  可以,但如果有两个event_base呢,

  用两个全局变量吗,我看不行。

  所以问题的本质是:要在GetPtr中获得一个so1的副本,好让so1的引用计数可以增加。

  struct Object:

  {

    shared_ptr<Object> GetPtr()

    {

      return ???;

    }

  };

  shared_ptr<Object> so1 = make_shared<struct Object>(new Object);

 

  结论是:使用shared_from_this

 

  struct Object:public enable_shared_from_this<Object>

  {

    shared_ptr<Object> GetPtr()

    {

      return shared_from_this();

    }

  };

 

  参考:

  https://en.cppreference.com/w/cpp/memory/enable_shared_from_this

posted on 2021-03-05 14:40  可鲁·贝洛斯  阅读(61)  评论(0)    收藏  举报

导航