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

时间:2017-05-11 04:52:40

标签: c++ qt dynamic-memory-allocation qlabel

此代码不动态分配内存,不会在窗口上显示任何标签。

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必须使用动态内存分配?

3 个答案:

答案 0 :(得分:5)

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

第一种情况是在堆栈上创建QLabel并且它会死掉"当你退出构造函数时。

在第二部分,它继续生活1)因为它是动态分配的,2)你实际上是为它分配一个父 - 这是你的主窗口。如果你不做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,但仍然可以通过将其移动到更广泛的范围来使用它。由于您的标签将显示在主窗口中,因此您可以创建类成员标签。不需要动态分配,因为只要您的窗口实例处于活动状态,它就会继续生效。

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

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

正如评论中所提到的(再次感谢!)此处不需要setParent(...),除非您想要除了内存管理以外的其他内容的父子关系。见下面的评论。

答案 1 :(得分:2)

  

此代码不动态分配内存,不会在窗口上显示任何标签。

那是因为一旦从构造函数返回,标签就会超出范围。标签的生命周期在下面注明。 if (window.location.hash) { $('li').one('click',function () { if (!window.run){ $(this).prependTo($(this).parent()); window.run = true; } }); $(document).ready(function () { var id = window.location.hash; $(id).trigger('click'); }); } <{1}}本身。

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 对象的存在与指向它的指针无关。

label
  

为什么QLabel必须使用动态内存分配?

不是。你碰巧给了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

答案 2 :(得分:1)

在堆栈上创建QLabel时,函数返回时会删除它。当父窗口小部件更新其显示时,QLabel不再存在。

在堆上创建它可以使它超出对函数的调用。