提问人:josh chatham 提问时间:11/17/2023 最后编辑:Jean-Baptiste Yunèsjosh chatham 更新时间:11/18/2023 访问量:73
当 dtor 不是虚拟的时,为什么 shared_ptr 和 unique_ptr 有不同的行为?
Why do shared_ptr and unique_ptr have different behavior when dtors are not virtual?
问:
所以,我知道不使多态类析构函数虚拟会导致未定义的行为,而正确的解决方法是使它们成为虚拟的。话虽如此,为什么shared_ptr在破坏时“拯救”你?(我在 RHEL 8 上使用 gcc/g++)
class Base
{
public:
~Base()
{
std::cout << "Base dtor" << std::endl;
}
};
class Derrived : public Base
{
public:
~Derrived()
{
std::cout << "Derrived dtor" << std::endl;
}
};
int main()
{
// Derrived dtor NOT called! (I understand why!)
{
std::unique_ptr<Base> b = std::make_unique<Derrived>();
}
// Derrived and Base dtor called! WHY???
{
std::shared_ptr<Base> b = std::make_shared<Derrived>();
}
}
我正在开发一个代码库,shared_ptr一unique_ptr就隐藏了内存泄漏 的物体,它坏了。花了一分钟才找出原因。这是一个简单的修复,但我可以看到这隐藏了很多内存泄漏。
现在我只是好奇为什么它不同?shared_ptr以某种方式跟踪对象的动态类型吗?
我尝试将shared_ptr更改为unique_ptr,期望相同的行为,但得到了不同的行为。
答:
来自 cppreference。
对于unique_ptr:
如果 T 是某个基 B 的派生类,则 隐式转换为 。默认删除程序 结果将对 B 使用运算符 delete, 导致未定义的行为,除非 B 的析构函数是虚拟的。请注意,std::shared_ptr 的行为不同:std::shared_ptr 将对类型 T 使用运算符 delete,即使 B 的析构函数不是虚拟的,拥有的对象也会被正确删除。
std::unique_ptr<T>
std::unique_ptr<B>
std::unique_ptr<B>
对于从另一个shared_ptr构造时shared_ptr(案例 8、9、10):
别名构造函数:构造一个共享的shared_ptr 初始值为 r 的所有权信息,但拥有 不相关和非托管指针 PTR。如果此shared_ptr是最后一个 该组超出范围,它将调用存储的删除程序 最初由 R 管理的对象
现在我只是好奇为什么它不同?shared_ptr以某种方式跟踪对象的动态类型吗?
unique_ptr被设计得尽可能高效。
shared_ptr显然可以共享该对象,因此您可能希望在该对象上使用不同的指针类型,然后需要跟踪原始删除程序。相反,如果删除在对象的一个或另一个shared_ptr上使用时的行为会有所不同,您会感到非常惊讶。
评论
shared_ptr
shared_ptr
unique_ptr
std::default_deleter
std::has_virtual_destructor
unique_ptr
评论
std::shared_ptr
有“动态”删除器...std::make_shared<Derrived>()
shared_ptr<Derived>
Derived*
Derived*
shared_ptr<Base>
shared_ptr<Derived>
Derived*
Base*
Derived*
std::shared_ptr