为什么我必须为 QLabel 动态分配内存才能工作?

Why do I have to dynamically allocate memory to QLabel for it to work?

这段代码没有动态分配内存,没有在window上显示任何标签。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel l;
    l.setText ("cdsadsaf");
    l.setParent (this);
}

动态分配内存后,标签显示出来。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel *label = new QLabel(this);
    label->setText("first line\nsecond line");
}

为什么 QLabel 工作需要动态内存分配?

当您在堆栈上创建一个 QLabel 时,它会在函数 returns 时被删除。当父小部件更新其显示时,QLabel 已不存在。

在堆上创建它允许它在函数调用之后继续存在。

不需要。你这里有典型的范围问题。

第一种情况在堆栈上创建 QLabel 并在退出构造函数时创建 "dies"。

在第二个它继续存在 1) 因为它是动态分配的 2) 你实际上为它分配了一个父级 - 这是你的主要 window。如果您不执行 2),效果将与第一种情况相同,但更糟 - 您将造成内存泄漏:

内存泄漏

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel *label = new QLabel(); # no parent
    label->setText("first line\nsecond line");
}

没有内存泄漏,因为父级被分配给标签

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel *label = new QLabel(this); # main window is the parent and will take care of destroying the label when its own destructor is called
    label->setText("first line\nsecond line");
}

您可以避免在堆上分配 QLabel,但仍然可以通过将其移动到更广泛的范围来使用它。由于您的标签要显示在主 window 中,您可以创建一个 class 成员标签。不需要动态分配,因为只要您的 window 实例存在,它就会一直存在。

class MainWindow : public QMainWindow
{
...
private:
  QLabel l;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    this->l.setText ("cdsadsaf");
}

如评论中所述(再次感谢!)此处不需要 setParent(...),除非您希望父子关系用于内存管理以外的其他事情。请参阅下面的评论。

This code which does not dynamically allocate memory, does not show any label on the window.

那是因为一旦您从构造函数 return 标签就超出了范围。标签的生命周期在下面注释。 label 一个 QLabel 本身。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel label;                // label is born
    label.setText ("cdsadsaf");  // label is alive
    label.setParent (this);      // label is alive
}                                // label dies

After dynamically allocating memory, the label shows up.

那是因为标签没有超出范围。指向它的指针确实如此,但这并不重要。请注意,label 只是一个指针,QLabel 对象独立于指向它的指针而存在。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QLabel *label = new QLabel(this);          // label is born, QLabel is born
    label->setText("first line\nsecond line"); // label is alive, QLabel is alive
}                                              // label dies, QLabel is alive

Why is dynamic memory allocation necessary for QLabel to work?

不是。由于使用动态分配,您碰巧给 QLabel 一个活下来的机会,但这只是巧合。

您可以使标签成为父对象本身的一部分 - 这样就不需要单独分配了。编译器将为您管理内存。

#include <QtWidgets>

class MainWindow : public QMainWindow {
  QWidget m_central;
  QGridLayout m_layout{&m_central};
  QLabel m_label{"Hello, World"};
public:
  MainWindow(QWidget * parent = {}) : QMainWindow{parent} {
    m_layout.addWidget(&m_label, 0, 0);
    setCentralWidget(&m_central);
  }
};

int main(int argc, char ** argv) {
  QApplication app{argc, argv};
  MainWindow w;
  w.show();
  return app.exec();
}