我知道我需要定义一个虚拟析构函数(即使我的类是最好的选择final
)。在我的例子中,我使用了类似 C 的结构(没有函数,没有默认值,只有普通成员)并使用继承来组成一个新结构。然后,我将一个指向基类的指针存储在其中,std::unique_ptr
并让 RAII 完成其余的工作。
我现在很好奇是否还需要显式添加虚拟析构函数以避免内存问题。
一个例子可能是:
#include <chrono>
#include <memory>
struct A {
std::chrono::milliseconds duration = std::chrono::milliseconds{-1};
int count = 0;
};
struct B {
int mode = 0;
};
struct C : public A, public B {
int foo = 1;
};
int main()
{
std::unique_ptr<A> base = std::make_unique<C>();
base.reset(); // I expect here that A,B and C are destructed properly
return 0;
}
类是多态的还是微不足道的都没有关系。
如果delete
在与它指向的对象的最派生类型不同类型的指针上调用(直到 cv 限定),并且指向的类型没有虚拟析构函数,则行为未定义。
这条规则的一个明显原因是基类子对象可能与最派生对象不在同一个地址。因此编译器无法知道传递给释放函数的偏移量需要是什么。
有人可能会争辩说,如果使用指向第一个基类子对象的指针,则具有普通析构函数的标准布局类不需要遵循此规则,但标准没有例外,并且您的类C
不是标准布局反正。
请参阅CWG 问题 1259作为非缺陷关闭。问题中提到的大小感知全局释放函数也是在 C++14 中引入的,这是使用基类指针在实践中可能会给您带来问题的另一个原因,即使析构函数是微不足道的并且地址没有偏移。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句