How to release pointer from boost::shared_ptr?

后端 未结 14 1595
刺人心
刺人心 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:49

    If your pointers are indeed unique do use std::unique_ptr or boost::scoped_ptr if the former is not available for your compiler. Otherwise consider combining the use of boost::shared_ptr with boost::weak_ptr. Check out the Boost documentation for details.

    0 讨论(0)
  • 2020-11-30 06:49

    I am using Poco::HTTPRequestHandlerFactory which expects to return a raw HTTPRequestHandler*, the Poco framework deletes the handler once the request finishes.

    Also using DI Sauce project to create the controllers, however the Injector returns shared_ptr which I cannot return directly, and returning handler.get() is no good either since the as soon as this function returns the shared_ptr goes out of scope and deletes then handler before its executed, so here is a reasonable (I think) reason to have a .release() method. I ended up creating a HTTPRequestHandlerWrapper class as follows :-

    class HTTPRequestHandlerWrapper : public HTTPRequestHandler {
    private:
        sauce::shared_ptr<HTTPRequestHandler> _handler;
    
    public:
        HTTPRequestHandlerWrapper(sauce::shared_ptr<HTTPRequestHandler> handler) {
            _handler = handler;
        }
    
        virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
            return _handler->handleRequest(request, response);
        }
    };
    

    and then the factory would

    HTTPRequestHandler* HttpHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
        URI uri = URI(request.getURI());
        auto path = uri.getPath();
        auto method = request.getMethod();
    
        sauce::shared_ptr<HTTPRequestHandler> handler = _injector->get<HTTPRequestHandler>(method + ":" + path);
    
        return new HTTPRequestHandlerWrapper(handler);
    }
    

    which satisfied both Sauce and Poco and works nicely.

    0 讨论(0)
  • 2020-11-30 06:52

    You need to use a deleter that you can request not to delete the underlying pointer.

    See this answer (which has been marked as a duplicate of this question) for more information.

    0 讨论(0)
  • 2020-11-30 06:52

    Kids, don't do this at home:

    // set smarty to point to nothing
    // returns old(smarty.get())
    // caller is responsible for the returned pointer (careful)
    template <typename T>
    T* release (shared_ptr<T>& smarty) {
        // sanity check:
        assert (smarty.unique());
        // only one owner (please don't play games with weak_ptr in another thread)
        // would want to check the total count (shared+weak) here
    
        // save the pointer:
        T *raw = &*smarty;
        // at this point smarty owns raw, can't return it
    
        try {
            // an exception here would be quite unpleasant
    
            // now smash smarty:
            new (&smarty) shared_ptr<T> ();
            // REALLY: don't do it!
            // the behaviour is not defined!
            // in practice: at least a memory leak!
        } catch (...) {
            // there is no shared_ptr<T> in smarty zombie now
            // can't fix it at this point:
            // the only fix would be to retry, and it would probably throw again
            // sorry, can't do anything
            abort ();
        }
        // smarty is a fresh shared_ptr<T> that doesn't own raw
    
        // at this point, nobody owns raw, can return it
        return raw;
    }
    

    Now, is there a way to check if total count of owners for the ref count is > 1?

    0 讨论(0)
  • 2020-11-30 06:54

    You can delete the shared pointer, which seems much the same to me. If pointers are always unique, then std::auto_ptr<> is a good choice. Bear in mind that unique pointers can't be used in STL containers, since operations on them do a lot of copying and temporary duplication.

    0 讨论(0)
  • 2020-11-30 06:56

    Here's a hack that might work. I wouldn't recommend it unless you're in a real bind.

    template<typename T>
    T * release_shared(std::shared_ptr<T> & shared)
    {
        static std::vector<std::shared_ptr<T> > graveyard;
        graveyard.push_back(shared);
        shared.reset();
        return graveyard.back().get();
    }
    
    0 讨论(0)
提交回复
热议问题