Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Qt使用原始指针? 在C++ C++编写了大量代码之后,我最近又回到Qt/C++编程。_C++_Qt_Pointers_Smart Pointers - Fatal编程技术网

为什么Qt使用原始指针? 在C++ C++编写了大量代码之后,我最近又回到Qt/C++编程。

为什么Qt使用原始指针? 在C++ C++编写了大量代码之后,我最近又回到Qt/C++编程。,c++,qt,pointers,smart-pointers,C++,Qt,Pointers,Smart Pointers,在浏览StackOverflow时,我经常会看到这样的帖子:在大多数情况下,答案的要点是“如果可以避免,就不要使用它们” 在C++中编译时,我现在主要尝试使用栈变量(通过代码> const >),或者如果需要,代码< > STD::SyrdYPPTR < /C> > RESP标准::在需要的地方唯一 回到Qt,我发现所有这些“原则”显然都被完全忽略了 我知道Qt使用自己的内存管理来处理原始指针,但我的问题是: P> QSharedPointer,4版.x是围绕C++环境中的java框架思想设

在浏览StackOverflow时,我经常会看到这样的帖子:在大多数情况下,答案的要点是“如果可以避免,就不要使用它们”

在C++中编译时,我现在主要尝试使用栈变量(通过代码> const <代码> >),或者如果需要,代码< > STD::SyrdYPPTR < /C> > RESP<代码>标准::在需要的地方唯一

回到Qt,我发现所有这些“原则”显然都被完全忽略了

我知道Qt使用自己的内存管理来处理原始指针,但我的问题是:


<> P> QSharedPointer,4版.x是围绕C++环境中的java框架思想设计的,采用C++ 98方式,设计了一个自己的实现。与RAII交互方法不同,它建立了“所有者”-“奴隶”关系,用框架的术语来说就是“父”和“子”。更重要的是,Qt使用PIMLP的概念——私有实现<代码>QObject您操作的对象并不是正在发生的事情的真实表示,它们是完全隐藏的内部实现的接口

根据设计,您必须创建子元素的QObject派生对象,并将所有权传递给所属对象。例如,如果窗口是所有者,则窗口内的按钮将是“从属”对象。删除所有者时,所有从属于它的对象也将被删除。所有
QObject
s都是线程感知的,但是
QWidgets
只能在主线程中工作。这将创建一个非所有者指针:

QWidget *myWidget = new QWidget(mainWindow);
在这种情况下,
main窗口
将拥有
QWidget
实例。但这一个是拥有的吗

QWidget *myWidget = new QWidget;
事实并非如此。它仍然归QApplication所有

QObjectDerivedClass *myWidget = new QObjectDerivedClass;
它是一个拥有指针,但该对象已注册为存在于我们的框架中。更重要的是,如果为任何实例分配了一个名称,就可以找到它,存储QObject以访问它们只是一种缓存优化

所有
QObjects
QWidgets
都是全局注册的,并且是可移植的。销毁
QApplicationCore
实例后,所有顶级QWidget都将被释放。至少在Qt4.x版本中,存在该规则之外的未记录异常,
QDesktopWidget
对象被忽略,即使它们是顶级小部件。因此,如果一个
QMainWindow
被强制作为它的子窗口出现在某个屏幕上,它就不会被破坏

现在开始使用信号插槽连接。在GUI中,一旦建立父子连接,某些处理程序就开始工作,但您可以添加新的处理程序。如果在由
QEventLoop
创建的消息泵的开始和结束之间删除子对象,则程序可能会遇到UB。为了避免这种情况,您必须调用
deleteLater()
,它在设计时刻标记要删除的对象。线程之间的信号处理是单独完成的。实际上,主事件循环是GUI中唯一与其他线程同步的部分

由于一些受支持的嵌入式平台强加了如此复杂的结构和在一个线程中工作的现有需求,与可能对性能的影响相比,在GUi框架中使用智能指针的需要可以忽略不计

在C++11之前,Qt拥有
QPointer
(并且仍然得到它),它知道QObject是否仍然存在,或者是否使用类似于所有者-子交互的机制

这种设计早于C++11,并且
QSharedPointer
仅出现在C++11之后,以满足用户维护用户定义数据模型的要求。它不支持某些功能,例如,你不能像ISO版本那样拥有原子版本,在5.x的最新版本之前,它只是部分原子版本
QAtomicPointer
既不是
QPointer
也不是
QSharedPointer
,它的作用类似于
std::atomic
QSharedPointer
虽然允许使用自定义的非独立删除程序,包括调用
deleteLater()

QSharedPointer objPtr{new MyDataQObject,&QObject::deleteLater};

假设
MyDataQObject
是从
QObject
派生的,
objPtr
将在托管对象的上下文中调用方法
deleteLater()
,而不是在销毁或重置时对托管指针使用
delete

Qt早于智能指针。使用指针没有什么错,问题在于未经管理地使用
new
delete
,正确使用
QObject
s会被其父母自动删除。实际上,Qt可以在没有
new
delete
的情况下使用,尽管Qt文档中有教程。暗示其他的东西。在切换到Qt之前,我使用了gtkmm,这是比较常见的。当我开始使用Qt时,所有这些
new
s和
delete
s困扰着我,我试图坚持以前在gtkmm中的做法。这实际上非常有效(需要考虑一些限制)。我在生产代码中也是这样使用它的。@Scheff'sCat delete在QT中很少使用,因为它有一种垃圾收集的形式(即参与信号槽处理的元素和可视元素不能被删除)。所有者对象自动删除其子对象,并且应用程序是所有GUI对象的所有者。这样的例子在达到堆栈大小的限制之前是有效的——所有对象都是在堆栈上创建的,并且必须在整个运行时都有效,所以它只能远程移植。但是5.6版之后更容易使用。@Swift FridayPie是的,因为Qt小部件通常为它们的孩子拥有所有权,您可能会看到
new
s,但不会看到
delete
s。我完全忘记了这一点,因为我很少使用
new
。链接考试中的小部件
QSharedPointer<MyDataQObject> objPtr { new MyDataQObject, &QObject::deleteLater };