从理论上讲,make_shared()
和shared_ptr
之间的一个区别是内存分配技术。make_shared()
应该使用单个块,而shared_ptr
应该使用两个块。make_shared()
的一个缺点是,即使只有一个weak_ptr
活动,也无法释放内存。
有人能解释一下为什么这个程序的输出总是相同的,而与我用来创建shared_ptr
的函数无关吗?
#include <iostream>
#include <memory>
class mc
{
public:
mc(int p):p_{p} {std::cerr<<"Constructor"<<std::endl;}
~mc() { std::cerr<<"Destructor"<<std::endl;}
private:
int p_;
};
std::weak_ptr<mc> wp3;
int main()
{
auto sp=std::make_shared<mc>(4);
auto sp2=sp;
auto sp3{sp};
wp3=std::weak_ptr<mc>{sp};
sp2.reset();
sp3.reset();
sp.reset();
for (int i =0;i< 5;i++) {std::cerr<<sp.use_count()<<std::endl;}
return 0;
}
我希望在最后调用析构函数方法,既然weak_ptr
仍然存在,为什么没有发生呢?
2条答案
按热度按时间7kjnsjlb1#
即使
shared_ptr
的内存不能被释放,当(非弱)refcount达到零时,它所持有的对象仍然会被销毁。对象销毁和内存释放是两个独立的操作,不需要同时发生。一般来说,由于
make_shared
的“一次分配”行为是一种优化,因此它不会对代码产生明显的影响。vybvopom2#
简单地使
std::weak_ptr
引用std::shared_ptr
并不增加shared_ptr
管理的对象的引用计数。std::weak_ptr
只是一个被动的观察者,直到它被锁定,返回一个新的shared_ptr
,该新的shared_ptr
要么1)引用共享对象,如果它还没有过期,则递增其引用计数,或者2)如果对象已经过期,则包含nullptr
。当共享对象的引用计数福尔斯0时(即不再有
std::shared_ptr
引用它),对象立即被销毁。在您的示例中,这发生在调用sp.reset()
时,而不是main()
退出时。您创建了3个shared_ptr
引用mc
对象,然后您reset()
这3个引用,从而在for
循环打印出引用计数之前销毁对象。如果
std::weak
增加了共享对象的引用计数,那么std::weak_ptr
的作用就完全失效了,它的行为就像std::shared_ptr
一样。std::weak_ptr
是一个“弱”(被动的,没有主动引用)智能指针,而std::shared_ptr
是一个“强”(主动引用)智能指针。