20

我已经对 Qt 进行了一段时间的编程,我想知道这两种情况之间有什么区别:

情况1:

标题:

QPushButton * button;

源文件:

button = new QPushButton(this);
button->setText("Button");
button->resize(100,100);

案例2:

标题:

QPushButton button;

来源:

button.setParent(this);
button.setText("Button");
button.resize(100,100);

两者都产生一个按钮,但我什么时候应该使用前者,什么时候使用后者?两者有什么区别?

4

5 回答 5

15

第一种和第二种情况的区别在于,当您使用指针和new语句分配按钮时,按钮的内存是在空闲存储(堆)中分配的。在第二条语句中,内存是在堆栈上分配的。

您宁愿在空闲存储中分配内存而不是在堆栈中分配内存的原因有两个。

  1. 堆栈的大小有限,如果您超出堆栈预算,您的程序将因堆栈溢出而崩溃。可以在空闲存储中分配更多的内存,如果内存分配失败,通常会发生bad_alloc异常。
  2. 堆栈上的分配是严格的后进先出(LIFO),这意味着您的按钮不能存在的时间超过{...}分配内存的代码块(之间的内容)。在空闲存储中分配内存时,作为程序员,您可以完全控制内存保持有效的时间(尽管粗心会导致内存泄漏)

在您的情况下,如果按钮只需要在调用函数期间存在,您可能可以在堆栈上分配按钮;如果按钮需要更长时间有效,请坚持免费商店

于 2013-09-11T16:01:23.927 回答
7

当父对象在销毁时自动删除子对象时,Qt 内存管理适用于对象的层次结构。这就是 Qt 程序在类似情况下总是使用指针的原因。

Qt 的内存管理:

Qt 维护对象的层次结构。对于小部件(可见元素),这些层次结构表示小部件本身的堆叠顺序,对于非小部件,它们仅表示对象的“所有权”。Qt 将子对象连同它们的父对象一起删除。

于 2013-09-11T15:57:41.403 回答
2

在第一种情况下,您正在动态分配按钮(这意味着当父级被销毁时它将被销毁)。在第二种情况下,按钮将在代码块结束时消失(意味着它超出了范围)。

当您想要使用第一个时QObject,您所指的不仅仅是创建它的块。

在您所指的类的上下文中(假设button在两种情况下都是成员变量)它没有太大区别。

此外,在使用多态性时,您可能希望使用指针。

于 2013-09-11T15:55:50.597 回答
1

一个有用的特定用法:发布自定义事件时,携带详细数据,例如:

/** support SWI... prolog_edit:edit_source(File) */
struct reqEditSource : public QEvent {
    QString file;
    QByteArray geometry;
    reqEditSource(QString file, QByteArray geometry = QByteArray())
        : QEvent(Type(User+1)), file(file), geometry(geometry) {}
};

你可以“解雇并忘记”他们:

qApp->postEvent(this, new reqEditSource(files[i], p.value(k).toByteArray()));

该事件将在其交付后被删除。

于 2013-09-11T17:16:17.703 回答
0

Qt 中的许多以对象为参数的函数实际上都以指向对象的指针为参数。那是因为“按值”传递对象实际上会创建对象的副本(通过复制构造函数)并传递该副本!创建对象的新副本有很多开销。同时,“通过引用”传递对象,即作为指针,只会传递一个32位的内存地址,这是一个非常轻量级的操作。

于 2017-10-24T23:48:22.597 回答