如果我重置一个std :: shared_ptr本身会发生什么 [英] What happens if I reset a std::shared_ptr to itself
问题描述
以下程序崩溃时出现glibc双重错误:
#include< iostream>
#include< memory>
class foo {
public:
foo()
{
std :: cout< foo constructed< std :: endl;
}
〜foo()
{
std :: cout< foo destructed< std :: endl;
}
};
int main(){
auto f = std :: make_shared< foo>();
std :: cout<< 复位前<< std :: endl;
f.reset(f.get());
std :: cout<< 复位后<< std :: endl;
return 0;
}
从这里我得到以下输出(后跟glibc错误):
foo created
重置前
foo destructed
重置后
foo destructed
很明显,在这种情况下,对象被销毁两次。一次通过复位,一次通过 std :: shared_ptr
超出范围。这实际上是我的期望。
在 cppreference 但是,我发现以下文本(位于 http://en.cppreference。 com / w / cpp / memory / shared_ptr / reset ):
如果*已经拥有一个对象,最后一个shared_ptr拥有它,对象被破坏通过拥有的删除,除非ptr是一个指针。
说,对象不应该像在我的例子中被销毁。非常令人惊讶,但如果标准说的这样。我不知何故误读了这个,或者是 std :: shared_ptr
的实现我可以不符合标准吗?
对于那些问我为什么这样做的人:
我目前正试图找出如何临时管理裸指针到由 new
和 new []
。这个想法是使用 std :: shared_ptr :: reset()
用无操作删除器替换删除器。另一种方法是用 try {stuff()} catch(...){delete x;
模板< class Y> void reset(Y * p);
效果:等效于 shared_ptr(p).swap / code>。
正如你所看到的那样, shared_ptr(p)
construction会为 p
创建一个带有新删除器的新计数,所以没有什么可以脱离它。它真的是最好的认为 std :: shared_ptr< T> :: get
作为严格观察员,并使用它来处理生命周期管理是一个告诉迹象,有
另一方面, std :: unique_ptr< T>
有 release
,这正是你需要的时候,你需要立即处理和处理所有权。也许你可以改变你的设计使用 std :: unique_ptr< T>
?如果你需要,总是可以创建一个 std :: shared_ptr< T>
。 (尽管 std :: shared_ptr< T>
从 std :: unique_ptr< T>
中选择删除者,您仍然需要在数组情况下的特殊处理,因为您可能希望 std :: shared_ptr< T *>
从 std :: unique_ptr< T [ >
。)
The following program crashes with a bad glibc double free error:
#include <iostream>
#include <memory>
class foo {
public:
foo()
{
std::cout << "foo constructed" << std::endl;
}
~foo()
{
std::cout << "foo destructed" << std::endl;
}
};
int main() {
auto f = std::make_shared< foo >();
std::cout << "Before reset" << std::endl;
f.reset( f.get() );
std::cout << "After reset" << std::endl;
return 0;
}
From this I get the following output (followed by the glibc error):
foo constructed
Before reset
foo destructed
After reset
foo destructed
So obviously in this case the object is destroyed twice. Once by the reset and once by the std::shared_ptr
going out of scope. This is actually what I would have expected.
On cppreference however I find the following text (found at http://en.cppreference.com/w/cpp/memory/shared_ptr/reset ):
If *this already owns an object and it is the last shared_ptr owning it, the object is destroyed through the owned deleter, unless ptr is a pointer to it.
In my opinion this actually says, that the object should not be destroyed as in my example. Quite surprising, but if the standard says so. Am I somehow misreading this, or is the implementation of std::shared_ptr
I have available not conforming to the standard?
For those who ask why I am doing this:
I am currently trying to figure out how to temporarily manage bare pointers to objects created by new
and new[]
. The idea is to use the std::shared_ptr::reset()
to replace the deleter with a no-op deleter. The alternative is to wrap the code with a try { stuff() } catch( ... ) { delete x; throw;}
kind of block.
The specification for that overload of reset
is given in 20.7.2.2.4 shared_ptr modifiers [util.smartptr.shared.mod], paragraph 3 (from n3290):
template<class Y> void reset(Y* p);
Effects: Equivalent to
shared_ptr(p).swap(*this)
.
As you can see, that shared_ptr(p)
construction creates a new count with new deleter for that p
, so nothing good can come off it. It really is the best to think of std::shared_ptr<T>::get
as strictly an observer, and using it to deal with lifetime management is a telltale sign that there is something wrong going on.
On the other hand, std::unique_ptr<T>
has release
, which is exactly what you need when you need to step in and deal with ownership yourself for an instant. Perhaps you can change your design to use std::unique_ptr<T>
? It's always possible to create a std::shared_ptr<T>
out of it if you need to, eventually. (Although while the std::shared_ptr<T>
picks the deleter from the std::unique_ptr<T>
, you still need special treatment in the array case as you probably want std::shared_ptr<T*>
from std::unique_ptr<T[]>
.)
这篇关于如果我重置一个std :: shared_ptr本身会发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!