boost::shared_ptr能否释放存储的指针而不删除它?
我在文档中没有看到release函数的存在,FAQ中也解释了为什么它不提供release函数,类似于不能对不唯一的指针执行release操作。我的指针是唯一的。如何释放我的指针? 或者使用哪个boost智能指针类可以允许我释放指针? 希望你不会说使用auto_ptr :)
boost::shared_ptr能否释放存储的指针而不删除它?
我在文档中没有看到release函数的存在,FAQ中也解释了为什么它不提供release函数,类似于不能对不唯一的指针执行release操作。我的指针是唯一的。如何释放我的指针? 或者使用哪个boost智能指针类可以允许我释放指针? 希望你不会说使用auto_ptr :)
不要这样做。Boost的FAQ条目:
Q. 为什么shared_ptr没有提供release()函数?
A. shared_ptr不能放弃所有权,除非它是unique(),因为其他的副本仍然会销毁对象。
考虑以下情况:
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() 返回的指针很难可靠地释放,因为源 shared_ptr 可能已使用自定义析构器创建。因此,在以下情况下这样做是安全的:它是指向对象的唯一 shared_ptr 实例(unique() 返回 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() );
shared_ptr<some_t>( this )
的东西传递给它时。只有使用NullDeleter
才能确保安全。 - Kirill V. Lyadvinskysmart_ptr
。 - curiousguy// 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;
}
现在,有没有办法检查引用计数的所有者总数是否> 1?
make_shared
,那么 release
将不会返回一个可用于 delete
的指针,因为 make_shared
分配内存的方式不同。2> weak_ptr
通常使用订阅模式,如果你没有运行 shared_ptr
析构函数,则 weak_ptr
的 lock()
方法将返回一个拥有该内存的有效 shared_ptr
。然而,由于引用计数现在加一了,它可能不会删除它。 - Fozishared_ptr::reset()
。boost::weak_ptr
(请参见boost文档)。weak_ptr
持有对对象的引用,但不会增加引用计数,因此仅存在弱引用时对象将被删除。原谅他们,因为他们不知道自己在做什么。 这个例子可以使用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<>
是一个不错的选择。请注意,由于对它们的操作会进行大量复制和临时复制,因此无法在STL容器中使用唯一指针。
share_ptr
(使用某个参数p
构造了一个share_ptr
),现在他想要执行相反的操作(撤销share_ptr
的构造)。 - curiousguy我不完全确定您的问题是否是关于实现这一点,但如果您想要一个行为类似于 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();
}
auto_ptr :: release
的定义:“将auto_ptr内部指针设置为null指针(表示它不指向任何对象),而不销毁当前由auto_ptr指向的对象”。此函数执行此操作;reset
将指针设置为null,并将指针复制到静态墓地对象中,以防止shared_ptr删除它。 - Mark Ransomrelease
的契约只是执行指定的操作。将“指针复制到静态墓地”不属于release
规范。 - curiousguyrelease_shared
函数之外是不可见的。 - Mark Ransomstatic
变量永远不会被销毁。 - curiousguy
auto_ptr
?如果它们是唯一的,那么就意味着它们永远不会被复制(因为如果只是暂时存在,多个引用将存在),那么auto_ptr
应该可以正常工作。或者,如果您不打算使用智能指针提供的生命周期管理,那么可以使用原始指针。 - jalfshared_ptr
,因为在C++11之前这可能是最好的方法。抛出shared_ptr
->unique_ptr
转换可能会很有用,当你真的想打破规则时,不能打破规则真的很痛苦! - Zero