如何决定堆栈中的内容?

How to decide what goes on stack?

假设我有一个名为 MainComponent 的 C++ class,它内部有几个 classes:WindowClass、InputClass、GameClass。主要功能设置如下:

int main()
{
    MainComponent app;
    app.start(); // Initializes the MainComponent class, opens window, starts game and all that.

    return 0;
}

MainComponent class 预计可能会变得非常大,因为包含了 GameClass 等对象。 MainComponent app 应该动态分配 new 吗?或者我应该在 MainComponent class 中用 new 分配 GameClass 对象吗?还是只要它运行良好就将其留在堆栈中就可以了还是什么?

取决于 'big' 的含义。 This link 显示了某些操作系统的默认堆栈大小限制。您需要确保在堆栈上分配的大小 MainComponent 远低于这些数字中的任何一个。

此外,如果某些东西是动态创建的,或者某些 arrays/assets 太大,属于 MainComponent 或另一个低于 MainComponent 的结构,那么你始终可以堆分配 struct/array/class,同时仍将 MainComponent 本身保留在堆栈上。

从概念上讲,将 MainComponent 保留在堆栈上更有意义,因为它的生命周期完全按照其在 main 函数中的范围建模。

要回答您更笼统的问题,如何决定堆栈中的内容?,请考虑三个方面:

  1. 所有权。特定数据结构的所有权是否明确?它是否明确属于特定函数(及其后代)或特定 struct/class 并且可以使用 RAII 建模?
  2. 生命周期。特定数据结构是否预期存在于与创建它的 class 或创建它的函数的生命周期非常相似的时间线内?范围是什么?
  3. 编译时知道大小吗?分配可变大小的数组时会出现这种情况。许多 STL 容器就是这种情况。在那种情况下,基本 struct/class 包括堆栈上的一些东西,然后维护指向堆分配结构的指针。

你说:

MainComponent class is expected to possibly get very big because of included objects of GameClass

对象大小不变。例如:empty std::string 与 very long std::string 具有相同的 sizeof,它对任何对象都是相同的。

sizeof(object) 是它在堆栈中占用的唯一字节。无论如何,剩下的都去了堆。

因此,如果您达到堆栈限制并出现堆栈溢出异常,那么您应该尝试将一些对象移动到堆中。或者如果它是单个对象(就像你的 MainComponent class 看起来是),你也可以使用 singleton 模式,或者只是将它声明为 static,以删除它从堆栈到其他内存段。