为什么我必须为 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();
}
这段代码没有动态分配内存,没有在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();
}