QT - 主窗口小部件 - 堆还是栈?

9

我有点困惑,不确定该在堆栈上还是堆上初始化主要的小部件。在《C++ GUI Programming with QT 4》中,主要的小部件是在堆栈上初始化的。在我继续之前,让我解释一下我的意思:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow mainWin;
    mainWin.show();
    return app.exec();
}

现在,也许这只是因为更安全,也许是因为他们不想让读者对QT中的内存分配产生困惑。省略从QObject继承的对象上的任何删除确实允许读者“忘记”QT对象的内存管理。但是,我的问题是,我们应该更喜欢哪种方法,是前者还是后者:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow* mainWin = new MainWindow;
    mainWin->show();
    int execReturn = app.exec();
    delete mainWin;
    return execReturn;
}

我提出这个问题的主要原因是我通常喜欢在选择堆和栈时遵循以下模式:
- 如果项目很大 - 堆 - 如果项目长期存在 - 堆 - 否则 - 栈
现在,我的问题归结为两个问题:
1. QWidget是否太大以至于我应该担心堆栈溢出? 2. 平均应用程序的堆栈有多大?除了显然的递归函数之外,什么情况下我应该担心堆栈溢出?
我意识到QWidget本身很少会导致堆栈溢出,但这当然还与应用程序的任何其他堆栈使用相关。

使用 sizeof 查看对象的大小。没有“平均堆栈”,它在应用程序之间变化很大,并且限制在平台之间也有很大的差异。如果您担心,而且由于这个问题很容易跟踪,而且绝对没有性能方面的影响,那就使用堆。 - Mat
你说它因应用程序而异,我想你是指堆栈使用情况,但可用情况呢?不妨不再寻找每个应用程序的平均值,而是在过去15年中Windows、Linux或Mac应用程序的最小堆栈大小是多少?基本上,如果我正在创建跨平台应用程序,我很好奇应该期望哪些限制。--- sizeof显示20,这准确吗?那似乎有点小。 - Serodis
@Serodis:sizeof 是准确的。 - Mat
2个回答

4
你选择堆栈的模式听起来很合理,但我不会过于担心对象的大小。任何大型对象都应该在内部使用堆。std::vector通常是三个指针的大小,但可能非常大。
我认为你不应该担心任何一个对象本身就足够大而导致堆栈溢出。虽然有可能,但肯定非常罕见(我没有见过这种情况)。
我建议也考虑简单性,你可以在堆上分配任何局部变量,然后在函数返回之前释放它,但这将是不必要的复杂,并且通常被认为是不好的实践。
堆栈大小通常通过链接器设置进行配置。在Windows上,默认为1MB。

这种 QMainWindow 堆叠的方式非常标准。它使得读者能够清晰地了解其生命周期和仅有一个实例的事实。 - Martin Beckett

3
我更喜欢使用基于堆栈的方法,因为它可以使代码更简洁。你对堆栈溢出的担忧是合理的,但这种情况发生的可能性非常小。
虽然我不知道QApplication和MainWindow的大小,但它们(大多数情况下)会使用堆来存储需要大量空间的内部数据结构。因此,你不需要太担心潜在的堆栈溢出问题。
通常,Windows应用程序有1MB的堆栈大小。但是,通过更改链接器选项:/STACK,你可以轻松更改它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接