如何释放从boost :: shared_ptr的指针?
-
20-09-2019 - |
题
可以提高:: shared_ptr的释放所存储的指针而不删除它?
我可以看到文档中没有释放函数存在,也是在帮助解释为什么它不提供释放功能,类似的东西释放不能说不是唯一的指针来完成。我的指针是唯一的。我怎样才能释放我的指点? 或提高智能指针类使用,让我释放的指针? 我希望你不会说使用auto_ptr:)
解决方案
您需要使用一个删除器,你可以要求不删除底层的指针。
看到这个答案(这一直标记为这个问题的对更多信息的一式两份)。
其他提示
别。 Boost的FAQ条目:
问即可。为什么shared_ptr不提供一个释放()函数?
<强> 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.
此外,通过释放()返回的指针就难以可靠地解除分配,作为源的shared_ptr可能已经用定制删除创建。
因此,在情况下,它是唯一的shared_ptr实例指向你的对象(唯一在()返回true)和对象不需要特殊缺失者,这将是安全的。我仍然怀疑你的设计,如果你使用了这样的.release()函数。
您可以使用假缺失者。然后指针不会被实际删除。
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计数的总计数是> 1
要再次让指针指向什么,可以调用shared_ptr::reset()
。
然而,这将删除对象指向当你的指针是最后参照到对象。此,在第一位置的智能指针然而,正是所需的行为。
如果你只是想不持有对象活着的引用,你可以创建一个boost::weak_ptr
(见的升压文档)。甲weak_ptr
保存到对象的参考,但不添加到参考计数,所以,当只有弱引用存在对象被删除。
共享的基础是信任。如果在你的程序某些情况下需要释放原始指针,它几乎是肯定shared_ptr
是错误的类型。
然而,最近,我想这样做太,因为我需要从不同的进程堆解除分配。最后,我被教会我使用一些旧的std::shared_ptr
决定是不是深思熟虑的。
我只是常规使用的这种类型的用于清理。但指针只是复制在几个地方。其实我需要一个std::unique_ptr
,其中(惊喜)具有release
功能。
原谅他们吧,他们不知道他们做什么。 本例将升压:: 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<>
是一个不错的选择。请记住,唯一的指针不能在STL容器中使用,因为它们的操作做了很多拷贝和临时复制的。
我不能完全肯定,如果你的问题是关于实现这一目标,但如果你想从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
此行为允许您共享资源(如阵列),那么后来重新使用资源,而所有的共享引用无效到此资源。
下面是可能的工作黑客攻击。除非你在一个真正的绑定是我不会推荐它。
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
的。查看提振细节文档。
我使用波索:: HTTPRequestHandlerFactory它期望返回原始HTTPRequestHandler *时,波索框架删除处理程序一旦请求完成。
另外使用DI酱项目以创建控制器,然而,注射器返回的shared_ptr我不能直接返回,和返回handler.get()是没有好处或者由于只要此函数返回的shared_ptr超出范围和然后,会删除其处理程序之前执行,所以这里是一个合理的(我认为)的理由有.release()方法。我结束了创建一个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);
}
其中满足既酱和波索和很好地工作。
我需要通过异步处理程序传递一个指针和保持自毁行为的情况下,失败的,但最终的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_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 *
两者的存储器泄漏