为什么关于Qt库的官方示例和教程从不使用智能指针?我只看到new
并delete
创建和销毁小部件.
我搜索了理由但我找不到它,我自己也没有看到它,除非它是出于历史原因或向后兼容性:不是每个人都希望程序在窗口小部件构造函数失败时终止,并通过try/catch处理它块只是丑陋(即使在少数地方使用).父小工具可能取得孩子的所有权这一事实也只能部分地解释我的事情,因为你仍然需要delete
在某种程度上为父母使用.
因为Qt依赖父子模型来管理Qobject资源.它遵循复合+责任链模式,从事件管理到内存管理,绘图,文件处理等......
实际上,尝试在共享\唯一指针中使用QObject 是过度工程(99%的时间).
您必须提供一个自定义删除器,它将调用deleteLater
您父母的qobject已在父对象中有引用.所以你知道只要父元素存在,对象就不会泄露.当你需要摆脱它时,你可以deleteLater
直接打电话.
没有父项的QWidget已经在Qapplication对象中有了引用.与第2点相同.
也就是说,你仍然可以在Qt中使用RAII.例如,QPointer在a上表现为弱引用QObject
.我会用QPointer
而不是QWidget*
.
注意:听起来不是太狂热,两个字:Qt + valgrind.
智能指针类std::unique_ptr
,std::shared_ptr
用于内存管理.拥有这样一个智能指针意味着你拥有指针.但是,在QObject
使用QObject
父级创建或派生类型时,所有权(清理的责任)将移交给父级QObject
.在这种情况下,标准库智能指针是不必要的,甚至是危险的,因为它们可能会导致双重删除.哎呀!
但是,当QObject
在堆上创建(或派生类型)而没有父项时,QObject
事物是非常不同的.在这种情况下,你不应该只是持有一个原始指针,而是一个智能指针,最好是一个std::unique_ptr
对象.这样你就获得了资源安全.如果您稍后将对象所有权交给父母,QObject
您可以使用std::unique_ptr
,如下所示:
auto obj = std::make_unique(); // ... do some stuff that might throw ... QObject parentObject; obj->setParent( &parentObject ); obj.release();
如果在给孤儿父母之前做的事情会引发异常,那么如果使用原始指针来保存对象,则会发生内存泄漏.但上面的代码可以防止这种泄漏.
现代C++建议不是一起避免原始指针,而是避免拥有原始指针.我可能会添加另一个现代C++建议:不要将智能指针用于其他程序实体所拥有的对象.
你已经回答了自己的问题:except if it's for historic reasons/backward compatibility
.像QT一样庞大的库不能假设使用该库的每个人都有支持C++ 11的编译器.new
并delete
保证存在于早期标准中.
但是,如果您确实支持使用智能指针,我会鼓励在原始指针上使用它们.
除了@Jamey所说的:
如果巧妙地设计它,您可能永远不必在窗口小部件上使用删除.假设您有一个主窗口,并且您正在创建它的自动对象并在事件循环中运行该窗口.现在,可以将此窗口小部件中的所有项目添加为其子项.因为您将它们作为子项直接/间接地添加到此MainWindow中,所以当您关闭此主窗口时,所有内容都将自动处理.只需要确保您创建的所有动态对象/小部件都是MainWindow的子/孙.因此无需显式删除..
QObject
已定义父级,程序的树状结构允许非常有效地管理内存.
Qt中的动态打破了这个不错的理想,例如传递原始指针.人们可以很容易地拿到一个dangling pointer
,但这是编程中的一个常见问题.
Qt智能指针实际上是一个弱引用,它QPointer
提供了一些STL糖果.
也可以混合std::unique_ptr
等,但它应该只用于程序中的非Qt机器.