弱指针、make_shared和内存释放

24
当存在至少一个weak_ptr时,shared_ptr的控制块将保持活动状态。如果使用make_shared创建共享指针,则意味着整个对象的内存都被保留。(对象本身会被正确析构,但由于控制块和对象的内存是一起分配的,就像make_shared一样,它们只能一起释放。)
我的理解正确吗?
这种行为似乎代表了一个问题,例如在著名的“缓存示例”中。对象的内存将永远被保留。
在任何实际情况下都是一个问题吗?在这种情况下(大对象和使用weak_ptr的意图),是否应该使用构造函数创建shared_ptr

2
是的,但请记住,许多“大型”对象将动态分配其自己的内存,例如由 std::vector 组成的对象,因此当对象被销毁时,动态分配的内存将被释放。只有在对象本身的大小很大时,例如一个大的 std::array,你才需要担心。 - Chris Drew
2
如果你担心异常安全性,可以使用make_unique代替,然后从你的unique_ptr构造一个shared_ptr,例如 std::shared_ptr<BigObject> ptr = std::make_unique<BigObject>(); - Chris Drew
2个回答

19

我的理解对吗?

是的。如果你的 weak_ptr 明显超出了(大的)对象的寿命并且内存紧缺,避免使用 make_shared 可能会有益。

但是,“大”在这里是通过 sizeof 来衡量的,并且许多从概念上来说“大”的对象(例如,除了 std::array 之外的大部分标准容器)在这个度量标准下相当小,因为它们分配额外的内存来存储其内容,这些内存一旦对象被销毁就会被释放。


3

我在VS2013中尝试过这个方法,你说得完全正确。当最后一个shared_ptr被销毁时,析构函数会被调用,因此与该对象相关的任何其他对象或内存都将被销毁,但如果使用make_shared创建了shared_ptr,则该内存直到最后一个weak_ptr被销毁时才会被销毁。

我认为,即使没有使用make_shared,如果lock()失败,也要清理或重置你的weak_ptr,因为它仍然会使用一些内存。


“清理或重置总是一个好习惯…” 是的,但并没有什么阻止实现自动执行这个操作。 - curiousguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接