非QObject派生类是否应该“总是”?被放入堆栈中?
来自 Symbian 世界,我习惯于尽可能多地使用堆以避免耗尽堆栈空间,尤其是在处理描述符时。 CBase 派生类总是在堆上动态分配,因为如果不这样做,它们的成员变量将保持未初始化状态。相同的约定是否适用于 QObject 派生类?
在 Qt 中,将 QString 等内容放在堆栈上似乎很常见。是字符串内容放在堆上,而 QString 作为堆栈上的容器,还是所有内容都放在堆栈上?
Coming from the Symbian world, I'm used to using the heap as much as possible to avoid running out of stack space, especially when handling descriptors. CBase derived classes were always dynamically allocated on the heap, since if they were not, their member variables would stay uninitialized. Does the same convention apply to QObject-derived classes?
In Qt it seems to be common to put, for example QString, on the stack. Are the string contents put on the heap while QString acts as a container on the stack, or is everything put on the stack?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如 sje397 所说:将 QString 和容器放在堆栈上是惯用的,因为它们是隐式共享的。它们的内部结构(pimpl 惯用语“d”指针)是在堆上创建的。在堆上创建对象本身也是没有意义的。只会导致内存管理麻烦,并且在将指针传递到周围的字符串/容器时会丢失预期的写时复制属性。
另一方面,在几乎所有情况下,您都希望在堆上创建 QObjects,否则它们会立即再次被破坏。它们不能被复制或分配(好吧,我们可以为自己的子类强制执行它,但是 QObject 语义就会被破坏),并且通常它们应该在创建它们的方法体中保留下来。
例外的是
QDialog
,它通常在堆栈上创建,然后是QDialog::exec
,它会阻塞直到对话框关闭。但即使这样严格来说也是不安全的,因为外部事件(RPC 调用、后台操作)可能会导致对话框在 exec 返回之前被其父级删除(如果父级本身被删除)。然后在堆栈上创建对话框将在展开堆栈时导致双重删除 ->碰撞。
As sje397 said: It's idiomatic to put
QString
and containers on the stack, as they are implicitly shared. Their internals (pimpl idiom "d" pointer) are created on the heap. There is no point in creating the object itself on the heap, too. Just causes memory-management hassles and you lose the intended copy-on-write properties when passing pointers to strings/containers around.QObjects
on the other hand you want to create on the heap in almost all cases, as otherwise they would be destructed again right away. They can't be copied or assigned (well, one can enforce it for own subclasses, but theQObject
semantics are broken then), and usually they are supposed to survive the method body they are created in.Exception is
QDialog
, which is often created on the stack, followed byQDialog::exec
, which blocks until the dialog is closed. But even that is strictly spoken unsafe, as external events (RPC calls, background operations) could cause the dialog to be deleted by its parent (if the parent itself is deleted) before exec returns.Then having the dialog created on the stack will cause double deletion when unwinding the stack -> crash.
QString 和许多其他 Qt 类使用隐式数据共享。这意味着内存通常是在堆上分配的。
QString, and many other Qt classes, use implicit data sharing. That implies that memory is generally allocated on the heap.