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

时间:2014-03-16 18:03:34

标签: c++ polymorphism raii

我一直在研究RAII(http://tomdalling.com/blog/software-design/resource-acquisition-is-initialisation-raii-explained/)并提出了许多问题!

  1. 在堆栈上初始化对象时有一些强有力的参数。在堆上分配内存是否有好的方案?

  2. 这对多态对象有何影响?例如,您有一个名为Biome的抽象基类,您需要一个生物群系列。这个容器需要存储OceanTundraDesert等对象。是否有任何问题或强有力的论据反对在堆栈上分配这些对象,但是然后存储指向这些对象的指针指向生物群系的指针容器? 我知道一旦封装对象超出范围,这些对象将被销毁,其指针将被发送到可能不存在的内存中。

2 个答案:

答案 0 :(得分:2)

  

有一些强大的参数可以初始化堆栈上的对象。在堆上分配内存是否有好的方案?

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

  

这如何与多态对象一起使用?例如,您有一个名为Biome的抽象基类,您需要一个生物群系列。这个容器需要存放海洋,苔原,沙漠等物体。

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

答案 1 :(得分:0)

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

  2. 不是很好。根据我的经验,多态类通常不适合RAII,因为多态类对象的对象生命周期通常与范围不对应。如果生命周期与范围相对应,则RAII仅为真正的RAII。

  3. 以下是您的示例的三种可能方案:

    第一个程序逻辑:对象在死亡时知道自己,对外部事件作出反应。在这种情况下,他们会通知他们的容器消亡,然后拨打delete this

    第二个程序逻辑:容器管理它们的生命周期,在这种情况下容器会在其析构函数中的每个元素上调用delete:

    for (auto element : m_elements) {
        delete element;
    }
    

    (用C ++ 11语法编写)

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

    重点是:这些场景中没有一个与RAII有任何关系,因为在每个场景中,生命周期都与范围不对应。