How to release pointer from boost::shared_ptr?

后端 未结 14 1597
刺人心
刺人心 2020-11-30 06:42

Can boost::shared_ptr release the stored pointer without deleting it?

I can see no release function exists in the documentation, also in the FAQ is explained why it

相关标签:
14条回答
  • 2020-11-30 06:57

    To let the pointer point to nothing again, you can call shared_ptr::reset().

    However, this will delete the object pointed to when your pointer is the last reference to the object. This, however, is exactly the desired behaviour of the smart pointer in the first place.

    If you just want a reference that does not hold the object alive, you can create a boost::weak_ptr (see boost documentation). A weak_ptr holds a reference to the object but does not add to the reference count, so the object gets deleted when only weak references exist.

    0 讨论(0)
  • 2020-11-30 07:00

    The basis of sharing is trust. If some instance in your program needs to release the raw pointer, it is almost for sure that shared_ptr is the wrong type.

    However, recently I wanted to do this too, as I needed to deallocate from a different process-heap. In the end I was taught that my older decision to use some std::shared_ptr was not thought-out.

    I just routinely used this type for cleanup. But the pointer was just duplicated on a few places. Actually I needed a std::unique_ptr, which (suprise) has a release function.

    0 讨论(0)
  • 2020-11-30 07:03

    I'm not entirely sure if your question is about achieving this, but if you want behaviour from a shared_ptr, where, if you release the value from one shared_ptr, all the other shared pointers to the same value become a nullptr, then you can put a unique_ptr in a shared_ptr to achieve that behaviour.

    void print(std::string name, std::shared_ptr<std::unique_ptr<int>>& ptr)
    {
        if(ptr == nullptr || *ptr == nullptr)
        {
            std::cout << name << " points to nullptr" << std::endl;
        }
        else
        {
            std::cout << name << " points to value " << *(*ptr) << std::endl;
        }
    }
    
    int main()
    {
        std::shared_ptr<std::unique_ptr<int>> original;
        original = std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(50));
    
        std::shared_ptr<std::unique_ptr<int>> shared_original = original;
    
        std::shared_ptr<std::unique_ptr<int>> thief = nullptr;
    
        print(std::string("original"), original);
        print(std::string("shared_original"), shared_original);
        print(std::string("thief"), thief);
    
        thief = std::make_shared<std::unique_ptr<int>>(original->release());
    
        print(std::string("original"), original);
        print(std::string("shared_original"), shared_original);
        print(std::string("thief"), thief);
    
        return 0;
    }
    

    Output:

    original points to value 50
    shared_original points to value 50
    thief points to nullptr
    original points to nullptr
    shared_original points to nullptr
    thief points to value 50
    

    This behaviour allows you to share a resource (like an array), then later reuse that resource while invalidating all the shared references to this resource.

    0 讨论(0)
  • 2020-11-30 07:10

    I needed to pass a pointer through async handlers and to keep the self-destruct behavior in case of failure but the final API expected a raw pointer, so I made this function to release from a single shared_ptr:

    #include <memory>
    
    template<typename T>
    T * release(std::shared_ptr<T> & ptr)
    {
        struct { void operator()(T *) {} } NoDelete;
        
        T * t = nullptr;
        if (ptr.use_count() == 1)
        {
            t = ptr.get();
            ptr.template reset<T>(nullptr, NoDelete);
        }
        return t;
    }
    

    If ptr.use_count() != 1 you shall get a nullptr instead.


    Do note that, from cppreference (bold emphasis mine):

    If use_count returns 1, there are no other owners. (The deprecated member function unique() is provided for this use case.) In multithreaded environment, this does not imply that the object is safe to modify because accesses to the managed object by former shared owners may not have completed, and because new shared owners may be introduced concurrently, such as by std::weak_ptr::lock.

    0 讨论(0)
  • 2020-11-30 07:10

    Easy solution, increase the reference and then leak the shared_pointer.

    boost::shared_ptr<MyType> shared_pointer_to_instance(new MyType());
    new boost::shared_ptr<MyType>();
    MyType * raw_pointer = shared_pointer_to_instance.get()
    

    This will clearly cause a memory leak of both the shared_ptr and the MyType *

    0 讨论(0)
  • 2020-11-30 07:12

    You could use fake deleter. Then pointers will not be deleted actually.

    struct NullDeleter {template<typename T> void operator()(T*) {} };
    
    // pp of type some_t defined somewhere
    boost::shared_ptr<some_t> x(pp, NullDeleter() );
    
    0 讨论(0)
提交回复
热议问题