非QObject派生类应该“总是”放在堆栈上吗?

时间:2010-08-05 07:26:44

标签: qt memory-management qobject qstring

来自Symbian世界,我习惯尽可能多地使用堆,以避免耗尽堆栈空间,尤其是在处理描述符时。 CBase派生类总是在堆上动态分配,因为如果它们不是,它们的成员变量将保持未初始化。相同的约定是否适用于QObject派生类?

在Qt中,将(例如QString)放在堆栈上似乎很常见。当QString充当堆栈上的容器时,字符串内容是否放在堆上,或者所有内容都放在堆栈上?

2 个答案:

答案 0 :(得分:10)

正如sje397所说:将QString和容器放在堆栈上是惯用的,因为它们是隐式共享的。他们的内部(pimpl成语“d”指针)在堆上创建。在堆上创建对象本身也没有意义。只是导致内存管理麻烦,并且在将指针传递给字符串/容器时会丢失预期的写时复制属性。

另一方面,

QObjects在几乎所有情况下都要在堆上创建,否则它们会立即再次被破坏。它们不能被复制或分配(好吧,可以为自己的子类强制执行它,但是QObject语义被破坏了),并且通常它们应该在创建它们的方法体中存活。 异常是QDialog,它通常在堆栈上创建,后跟QDialog::exec,它会一直阻塞,直到对话框关闭。但即使这样也严格说不安全,因为外部事件(RPC调用,后台操作)可能会导致对象在exec返回之前被父节点删除(如果父节点被删除)。 然后在堆栈上创建对话框将在展开堆栈时导致双重删除 - >崩溃。

答案 1 :(得分:1)

QString和许多其他Qt类使用implicit data sharing。这意味着内存通常在堆上分配。