gpt4 book ai didi

c++ - 为什么 std::shared_ptr 从基类和派生类调用析构函数,而 delete 仅从基类调用析构函数?

转载 作者:IT老高 更新时间:2023-10-28 23:12:41 26 4
gpt4 key购买 nike

为什么当使用 std::shared_ptr 释放时,当第二个示例仅从基类调用析构函数时,会同时从基类和派生类调用析构函数?

class Base
{
public:
~Base()
{
std::cout << "Base destructor" << std::endl;
}
};

class Derived : public Base
{
public:
~Derived()
{
std::cout << "Derived destructor" << std::endl;
}
};

void virtual_destructor()
{
{
std::cout << "--------------------" << std::endl;
std::shared_ptr<Base> sharedA(new Derived);
}

std::cout << "--------------------" << std::endl;
Base * a = new Derived;
delete a;
}

输出:

--------------------
Derived destructor
Base destructor
--------------------
Base destructor

我期望在这两种情况下都有相同的行为。

最佳答案

delete a是未定义的行为,因为类 Base没有虚拟析构函数和 *a 的“完整对象” (更准确地说:包含 *a 的最衍生对象)不是 Base 类型.

共享指针是使用推导删除器创建的,该删除器删除 Derived * ,因此一切都很好。

(推导出的删除器的效果就是说delete static_cast<Derived*>(__the_pointer))。

如果你想用共享指针重现未定义的行为,你必须立即转换指针:

// THIS IS AN ERROR
std::shared_ptr<Base> shared(static_cast<Base*>(new Derived));

从某种意义上说,这是共享指针行为的正确方式:因为您已经为类型删除的删除器和分配器的虚拟查找付出了代价,所以这是公平的那么您不必为析构函数的另一个虚拟查找付费。类型删除删除器会记住完整的类型,因此不会产生更多开销。

关于c++ - 为什么 std::shared_ptr 从基类和派生类调用析构函数,而 delete 仅从基类调用析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20802810/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com