如何从boost :: shared_ptr释放指针?
boost :: shared_ptr可以释放存储的指针而不删除它吗?
我可以看到文档中不存在发布函数,在常见问题中解释了为什么它不提供发布函数,就像发布不能在不唯一的指针上发布一样。 我的指针是独一无二的。 我怎样才能释放我的指针? 或者哪个提高智能指针类使用,将允许我释放指针? 我希望你不会说使用auto_ptr 🙂
您需要使用删除程序,您可以请求不删除基础指针。
看到这个答案 (已被标记为这个问题的重复)以获取更多信息。
别。 Boost的FAQ条目:
Q。 为什么shared_ptr不提供release()函数?
A。 shared_ptr不能放弃所有权,除非它是唯一的(),因为另一个副本仍然会销毁对象。
考虑:
shared_ptr<int> a(new int); shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2 int * p = a.release(); // Who owns p now? b will still call delete on it in its destructor.
此外,由release()返回的指针将很难可靠地释放,因为可以使用定制的删除器创build源shared_ptr。
所以,如果唯一的shared_ptr实例指向你的对象(当unique()返回true),并且对象不需要特殊的删除器,这将是安全的。 如果你使用了.release()函数,我仍然会质疑你的devise。
你可以使用假删除器。 那么实际上指针不会被删除。
struct NullDeleter {template<typename T> void operator()(T*) {} }; // pp of type some_t defined somewhere boost::shared_ptr<some_t> x(pp, NullDeleter() );
孩子们,不要在家里这样做:
// 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; }
现在有没有办法检查ref count的所有者总数是否大于1?
要让指针再次指向什么,可以调用shared_ptr::reset()
。
但是,这将删除指针指向对象的最后一个引用时指向的对象。 然而,这首先是智能指针所期望的行为。
如果你只是想要一个不包含对象的引用,你可以创build一个boost::weak_ptr
(见boost文档 )。 weak_ptr
保存对该对象的引用,但不会添加到引用计数中,因此当只有弱引用存在时,该对象将被删除。
分享的基础是信任。 如果程序中的某个实例需要释放原始指针,几乎肯定shared_ptr
是错误的types。
但是,最近我也想这样做,因为我需要从不同的进程中释放堆。 最后,我被告知,我以前的决定使用一些std::shared_ptr
没有被认为是。
我只是经常使用这种types的清理。 但指针只是在几个地方复制。 其实我需要一个std::unique_ptr
,(惊喜)有一个release
function。
原谅他们,因为他们不知道他们做什么。 这个例子适用于boost :: shared_ptr和msvs std :: shared_ptr没有内存泄漏!
template <template <typename> class TSharedPtr, typename Type> Type * release_shared(TSharedPtr<Type> & ptr) { //! this struct mimics the data of std:shared_ptr ( or boost::shared_ptr ) struct SharedVoidPtr { struct RefCounter { long _Uses; long _Weaks; }; void * ptr; RefCounter * refC; SharedVoidPtr() { ptr = refC = nullptr; } ~SharedVoidPtr() { delete refC; } }; assert( ptr.unique() ); Type * t = ptr.get(); SharedVoidPtr sp; // create dummy shared_ptr TSharedPtr<Type> * spPtr = (TSharedPtr<Type>*)( &sp ); spPtr->swap(ptr); // swap the contents ptr.reset(); // now the xxx::shared_ptr is empy and // SharedVoidPtr releases the raw poiter but deletes the underlying counter data return t; }
你可以删除共享指针,这对我来说似乎很相似。 如果指针总是唯一的,那么std::auto_ptr<>
是个不错的select。 请记住,STL容器中不能使用唯一的指针,因为它们的操作会执行大量的复制和临时重复。
这是一个可能工作的黑客。 我不会推荐它,除非你在真正的约束。
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(); }
如果你的指针确实是唯一的,如果前者不适用于你的编译器,则使用std::unique_ptr
或boost::scoped_ptr
。 否则考虑将boost::shared_ptr
和boost::weak_ptr
结合使用。 查看详细的Boost文档 。
我正在使用Poco :: HTTPRequestHandlerFactory,期望返回一个原始的HTTPRequestHandler *,一旦请求完成,Poco框架删除处理程序。
同样使用DI Sauce项目来创build控制器,但是Injector返回了我不能直接返回的shared_ptr,并且返回handler.get()也不行,因为只要这个函数返回了shared_ptr就离开了scope并删除了handler在执行之前,所以这是一个合理的(我认为)有一个.release()方法的理由。 我最终创build了一个HTTPRequestHandlerWrapper类,如下所示:
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); } };
然后工厂会
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); }
既满足酱油又适合波科,效果很好。
我需要通过asynchronous处理程序传递一个指针,并在失败的情况下保持自毁行为,但最终的API期望一个原始指针,所以我让这个函数从一个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; }
如果ptr.use_count() != 1
你应该得到一个nullptr
。
我不完全确定你的问题是关于如何实现这一点,但如果你想从一个shared_ptr
行为,其中,如果你从一个shared_ptr
释放值,所有其他共享指针为相同的值成为nullptr,那么你可以把一个unique_ptr
放在一个shared_ptr
来实现这个行为。
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; }
输出:
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
此行为允许您共享资源(如数组),然后再使用该资源,同时使对该资源的所有共享引用无效。
简单的解决scheme,增加参考,然后泄漏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()
这显然会导致shared_ptr和MyType的内存泄漏*