【问题标题】:how can Qt delete QObjects?Qt如何删除QObjects?
【发布时间】:2018-11-17 01:43:53
【问题描述】:

据我了解,以下代码是创建 QObject 的绝佳方式

QLabel *label = new QLabel("label");
QWidget window;
label->setParent(&window);
window.show();

当我阅读无处不在时,“父对象拥有新创建对象的所有权 - 并最终调用删除”,或者“复合对象拥有子对象的所有权,只要育儿有搞定了,你可以放心,当父级被销毁时,子级QObjects也会被销毁”(来自How does Qt delete objects ? And what is the best way to store QObjects?

谁能告诉我 Qt 如何“获得”一个 QObject 的所有权?从技术上讲:Qt(它是一个库并有自己的运行时)如何在我用来自不同的操作符 new 创建的指针上调用操作符 delete运行?为什么不崩溃?

编辑

我正在添加此参考,因为问题的全部意义来自于此:

“在 DLL 中运行的代码可能使用不同的 C++ 运行时库,这意味着堆的布局将不同。DLL 可能完全使用不同的堆。

在 DLL 分配的指针上调用 delete(在主程序中)(反之亦然)将导致(最好的​​情况)立即崩溃或(最坏的情况)内存损坏,这需要一段时间才能找到。 "(来自C++ mix new/delete between libs?

【问题讨论】:

  • 你可能太努力了。 :-) Qt 代码将执行delete label;,就像您的代码可以执行的操作一样。没有区别,没有魔法。
  • 但 Qt 的删除操作符与我的不同,因为库有自己的新/删除操作符,不应混合在 DLL 中运行的代码可能使用不同的 C++ 运行时库,这意味着堆的布局会有所不同。 DLL 可能完全使用不同的堆。
  • 问题的新部分是关于别的东西。如果你随机混合 DLL,比如一些 Debug 模式和一些 Release 模式,或者使用不同的编译器,你遇到问题。但是,如果所有内容都使用相同的编译器使用相同的设置进行编译,那么所有内容都将使用相同的语言运行时。然后就没有问题了。
  • 您必须使用使用相同编译器编译的 Qt 工具包,因此(至少在 Windows 上),我们有不同的工具包代表相同版本的 Qt,但使用不同的编译器编译...
  • 我有错误的假设,即即使使用相同的编译器、版本或配置也可能存在多个堆管理。谢谢

标签: c++ qt qt4


【解决方案1】:

让源代码说话,而不仅仅是答案。这是QObject's internals 所做的:

for (int i = 0; i < children.count(); ++i) {
    currentChildBeingDeleted = children.at(i);
    children[i] = 0;
    delete currentChildBeingDeleted;
}
children.clear();

上面代码的函数在析构函数中被调用。所以,这很简单。父级存储指向其所有子级的指针。当调用父级的析构函数时,它会删除它的所有子级。这是递归的,因为在对象上调用 delete 会调用其析构函数

为什么 Qt 可以安全删除而不用担心运行时库

实际上,由于名称修饰,导出 C++ 接口几乎迫使您使用相同版本的编译器和运行时库。这以非常粗略的方式允许 Qt 假设 delete 可以安全调用。

【讨论】:

  • 我更新了问题以使其更加清晰。谢谢
【解决方案2】:

对于 Qt(它是一个库并且有自己的运行时)

这是您的假设错误的地方。首先,操作系统没有“运行时”之类的东西。 “运行时”是一个信息性术语。

现代操作系统有:二进制可执行文件、共享库(又名动态链接库、DLL、静态库、进程、线程等)。

在这种情况下,您的可执行文件和 Qt 共享库被加载到 SAME 进程中,这意味着它们之间共享内存。这意味着您的可执行文件可以看到 Qt 内存,相反 Qt 可以看到您的内存。

【讨论】:

  • 我更新了问题以使其更加清晰。谢谢
  • @user815129 这适用于 C 接口。通过 C++ 创建接口时,您实际上必须具有相同的运行时,因为名称修改是/可能不同,即使对于同一编译器的不同版本。
  • 你考虑过你的代码和Qt使用同一个标准库的情况吗?
  • 因为我没有从源代码编译 qt,也没有包含 qt 源代码,所以我不能确定..当然我在某些假设上是错误的,因为给定的例子是绝对正确的跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
相关资源
最近更新 更多