gpt4 book ai didi

c++ - 如何在删除操作中推导出多态对象的大小?

转载 作者:行者123 更新时间:2023-12-05 03:22:50 30 4
gpt4 key购买 nike

我知道SO上有很多类似的问题和我要问的问题相关,我看了很多还是觉得有点模糊,所以我决定问这个问题。

给定以下代码:(与 this 问题中的代码基本相同)

class A {
public:
int a;
};

class B : public A {
public:
int b;
};

int main() {
A* p = new B;
delete p;
}

我知道删除 p 而没有在 A 中定义 virtual 析构函数是标准中指定的 undefined behavior,此后可能发生任何事情。但是,我感兴趣的是堆上多态对象的大小是如何确定的。

我发现关于 SO 的两个说法可能是矛盾的:(或者我可能误解了)

  • 我们需要virtual析构函数来提供关于堆上对象的信息,以便通过基类指针删除对象。

    可能的 reference

    在我对这种实现的理解中,如果我们有virtual 析构函数,delete p; 将首先调用B 的析构函数(并且它知道调用的第一个 virtual 析构函数将对应于真正在堆上的对象的类型),并且 B 的析构函数知道对象的大小键入 B,因此删除操作可以从调用的第一个析构函数中提取该信息,并在析构函数调用完成后使用它来释放堆上的内存。

    如果这是幕后发生的事情,那么上面代码中的delete p;将无法释放int b占用的堆内存,因为在上述情况下,调用的第一个(也是唯一的)析构函数是 A 的析构函数,并且没有要为删除操作提取的有关 int b 的信息。

  • 堆可以“自动”推导出多态对象的大小。

    可能的引用资料:12

    如果这是幕后发生的事情,那么上面代码中的delete p;将能够释放int b占用的堆内存。在这种情况下,delete p;“意外地”工作正常,因为 B 的对象没有从“其他地方”获取资源(例如,没有指针的数据成员)。

请问以上两种理解哪一种是正确的?

如果堆可以推断出多态对象的信息,请问堆到底是怎么做到的?

最佳答案

这是 ABI 的一部分。

在通常用于 Linux 的 Itanium ABI 上,vtable 记录了虚拟析构函数的两个条目。一个条目调用析构函数但不调用 delete。这是完整的对象析构函数。一个条目调用析构函数并删除。这是删除析构函数。 See here.

由于删除析构函数是虚拟的并且是特定于类型的,因此它显然具有完整对象的大小。

其他答案对此有点混淆。销毁和删除是两个逻辑步骤,但通常提供组合形式,因为否则很难满足要求。 new 不会也不能在对象分配本身中存储大小信息(对于非数组情况)。并且该大小是必需的,因为 sized operator delete 具有优先权。而且实现不能依赖于特定的行为,因为这些函数是全局可替换的,因此不同的 TU 可以定义它们。

关于c++ - 如何在删除操作中推导出多态对象的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72611538/

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