LiK*_*Kao 5 c++ shared-ptr c++11
以下程序崩溃时出现错误的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 << "Before reset" << std::endl;
f.reset( f.get() );
std::cout << "After reset" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从这里我得到以下输出(后跟glibc错误):
foo constructed
Before reset
foo destructed
After reset
foo destructed
Run Code Online (Sandbox Code Playgroud)
很明显,在这种情况下,对象被销毁两次.一旦通过重置和一次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()no-op删除器替换删除器.另一种方法是用try { stuff() } catch( ... ) { delete x; throw;}一种块包装代码.
该重载的规范reset在20.7.2.2.4 shared_ptr修饰符[util.smartptr.shared.mod],第3段(来自n3290)中给出:
Run Code Online (Sandbox Code Playgroud)template<class Y> void reset(Y* p);效果:相当于
shared_ptr(p).swap(*this).
正如你所看到的那样,这种shared_ptr(p)构造为这个构造创建了一个带有新删除器的新计数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[]>.)