如何决定堆栈中的内容?
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
函数中的范围建模。
要回答您更笼统的问题,如何决定堆栈中的内容?,请考虑三个方面:
- 所有权。特定数据结构的所有权是否明确?它是否明确属于特定函数(及其后代)或特定 struct/class 并且可以使用 RAII 建模?
- 生命周期。特定数据结构是否预期存在于与创建它的 class 或创建它的函数的生命周期非常相似的时间线内?范围是什么?
- 编译时知道大小吗?分配可变大小的数组时会出现这种情况。许多 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
,以删除它从堆栈到其他内存段。
假设我有一个名为 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
函数中的范围建模。
要回答您更笼统的问题,如何决定堆栈中的内容?,请考虑三个方面:
- 所有权。特定数据结构的所有权是否明确?它是否明确属于特定函数(及其后代)或特定 struct/class 并且可以使用 RAII 建模?
- 生命周期。特定数据结构是否预期存在于与创建它的 class 或创建它的函数的生命周期非常相似的时间线内?范围是什么?
- 编译时知道大小吗?分配可变大小的数组时会出现这种情况。许多 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
,以删除它从堆栈到其他内存段。