c++使用RAII与多态性和堆栈分配

C++ Using RAII with Polymorphism and Stack Allocation

本文关键字:堆栈 分配 多态性 使用 RAII c++      更新时间:2023-10-16

我一直在研究RAII (http://tomdalling.com/blog/software-design/resource-acquisition-is-initialisation-raii-explained/),并有一些问题!

  1. 对于在堆栈上初始化对象有一些强有力的参数。有没有在堆上分配内存的好场景?

  2. 这是如何与多态对象工作的?例如,您有一个称为Biome的抽象基类,并且您需要一个生物群落的容器。该容器需要存储Ocean, Tundra, Desert等对象。在堆栈上分配这些对象,然后将指向这些对象的指针存储在指向Biome的指针容器中,是否存在任何问题或强烈的反对意见?我知道,一旦封装对象超出作用域,这些对象将被销毁,它们的指针将被定向到可能不存在的内存中。

对于初始化堆栈上的对象,有一些强有力的参数。有没有在堆上分配内存的好场景?

当对象的数量或它们的实际类型仅在运行时(而不是在编译时)知道,或者当它很大时,您当然需要在堆中分配对象。你不希望有大的调用堆栈帧(一个典型的帧应该小于1千字节,因为整个堆栈小于2兆字节,你可以有递归的,或者只是非常深的函数)。

这是如何工作的多态对象?例如,您有一个名为Biome的抽象基类,并且您需要一个生物群落的容器。此容器需要存储海洋,苔原,沙漠等对象。

容器实际上将存储指向这些对象的指针。当然,您可能希望使用智能指针。

  1. 。RAII基于自动对象销毁,即编译器自动插入的析构函数调用。(编辑:我希望你的问题只是关于堆+RAII,而不是堆一般!)

  2. 不太好。根据我的经验,多态类通常不适合RAII,因为多态类对象的对象生命周期通常不对应于作用域

  3. 只有生命周期100%符合作用域时,RAII才是真正的RAII。

下面是你的例子的三种可能的场景:

第一个程序逻辑:对象知道自己何时死亡,对外部事件作出反应。在这种情况下,它们通知容器它们的终止,然后调用delete this

第二个程序逻辑:容器管理的生命周期,在这种情况下,容器将对析构函数中的每个元素调用delete:
for (auto element : m_elements) {
    delete element;
}

(c++ 11语法)

第三个程序逻辑:对象由各种不同的组件所拥有,而不仅仅是容器,并且只有当最后一个组件死亡时它们才会死亡。在这种情况下,您可能会发现std::shared_ptr(或c++ 11之前版本的boost::shared_ptr)很有用。

关键是:这些场景都与RAII没有任何关系,实际上,因为在每个场景中,生命周期都不对应于作用域。