shared_from_this called from constructor

前端 未结 7 1967
一生所求
一生所求 2021-02-03 21:31

I have to register an object in a container upon its creation. Without smart pointers I\'d use something like this:

a_class::a_class()
{
    register_somewhere(t         


        
7条回答
  •  情书的邮戳
    2021-02-03 22:16

    I came up with a helper class for that problem:

    template 
    class ImmediatelySharedFromThis : public std::enable_shared_from_this {
        typedef std::unique_ptr> MallocGuard;
        typedef std::shared_ptr SharedPtr;
    
        // disallow `new MyClass(...)`
        static void *operator new(size_t) = delete;
        static void *operator new[](size_t) = delete;
        static void operator delete[](void*) = delete;
    protected:
        typedef std::pair SharingCookie;
    
        ImmediatelySharedFromThis(SharingCookie cookie) {
            MallocGuard &ptr = cookie.first;
            SharedPtr &shared = cookie.second;
            // This single line contains the actual logic:
            shared.reset(reinterpret_cast(ptr.release()));
        }
    public:
        // Create new instance and return a shared pointer to it.
        template 
        static SharedPtr create(Args &&...args) {
            // Make sure that the memory is free'd if ImmediatelySharedFromThis
            // is not the first base class, and the initialization
            // of another base class throws an exception.
            MallocGuard ptr(aligned_alloc(alignof(Impl), sizeof(Impl)), free);
            if (!ptr) {
                throw std::runtime_error("OOM");
            }
    
            SharedPtr result;
            ::new (ptr.get()) Impl(SharingCookie(ptr, result),
                                   std::forward(args)...);
            return result;
        }
    
        static void operator delete(void *ptr) {
            free(ptr);
        }
    };
    
    class MyClass : public ImmediatelySharedFromThis {
        friend class ImmediatelySharedFromThis;
    
        MyClass(SharingCookie cookie, int some, int arguments) :
            ImmediatelySharedFromThis(cookie)
            // You can pass shared_from_this() to other base classes
        {
            // and you can use shared_from_this() in here, too.
        }
    public:
        ....
    };
    
    ...
    
    std::shared_ptr obj = MyClass::create(47, 11); 
    

    A bit ugly, but it works.

提交回复
热议问题