C++ - 为什么我要在堆上创建这些小部件?

Dav*_*log 6 c++ qt

使用C++和Qt创建GUI时,您可以创建一个标签,例如:

QLabel* label = new QLabel("Hey you!", centralWidgetParent);
Run Code Online (Sandbox Code Playgroud)

这会在堆上创建对象并保持在那里,直到我手动删除它或者父进程被销毁.我现在的问题是为什么我需要一个指针呢?为什么不在堆栈上创建它?

//Create a member variable of Class MainWindow
QLabel label;

//Set parent to show it and give a text so the user can see it
    QWidget* centralWidget = new QWidget(this); //Needed to add widgets to the window
    this->setCentralWidget( centralWidget ); 
    label.setParent(centralWidget);
    label.setText( "Haha" );
Run Code Online (Sandbox Code Playgroud)

这工作正常,我可以看到标签,它没有消失.

我们在C++中使用指针让一些东西活得更长,这样我们就可以在各种范围内使用一个对象.但是当我创建一个成员变量时,它会不会停留直到对象被销毁?

编辑:也许我没有说清楚.这是MainWindow类:

class MainWindow : public QMainWindow
{
    Q_OBJECT
    QLabel label; //First introduced here...

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
};

//Constructor
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QWidget* centralWidget = new QWidget(this);
    this->setCentralWidget( centralWidget );
    label.setParent(centralWidget);
    label.setText( "Haha" );
}
Run Code Online (Sandbox Code Playgroud)

Nem*_*ric 8

如果你label超出范围,QLabel::~QLabel将调用析构函数().来自文档:

销毁该对象,删除其所有子对象.

没有必要在堆上创建对象 - 您可以将对象放在堆栈上,但是您需要对对象的生命周期负责(关于在堆上分配数据的问题最大的问题之一是"谁和什么时候应该删除这些对象?",在Qt中它由层次结构处理 - 每当你删除你的小部件时,所有子小部件都将被删除).

为什么你的程序工作 - 我不知道 - 它可能不起作用(label在范围的最后被销毁).另一个问题是 - label如果您没有对它的引用,您将如何更改(例如某些插槽中)的文本?

编辑我刚刚看到你label是你的成员MainWindow.拥有一个完整的对象,而不是作为类成员的对象的指针是完全没问题的,因为它不会被破坏MainWindow.请注意,如果你创建这样的实例MainWindow:

MainWindow *w = new MainWindow();
Run Code Online (Sandbox Code Playgroud)

label 将在堆上创建.


Seb*_*edl 6

因为这就是 Qt 的设计方式。我意识到这不是一个非常令人满意的答案,但 Qt 只是被设计为“在堆上创建小部件,父母负责删除他们的孩子”。

意识到 Qt 的起源是古老的,比我们认为的“现代 C++”还要古老。


Tha*_*eux 5

要记住的另一件事是 Qt 使用所谓的 pimpl 范式,其中对象数据在您实际实例化的类之后隐式共享和管理。见这里:http : //qt-project.org/wiki/Dpointer

最重要的是,如果您在堆栈上进行分配以避免使用堆,那么 Qt 只是在您身上拉了一个快速分配并使用堆。