此代码是否提供内存泄漏?
Does this code provide memory leaks?
我终于安装了 Ubuntu 并设置了 Qt+Valgrind 以防止内存泄漏,这是我在 Windows 中无法做到的。所以我不明白这段代码是否会导致内存泄漏?事实上,Valgrind 说我只有 500 多个问题,但与泄漏无关。我
#include <QWidget>
#include <QFrame>
#include <QVBoxLayout>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget * wdgt = new QWidget; //this line should be the cause of leakage
//if it exist (as far as i know)
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
frame->setLineWidth(5);
layout->addWidget(frame);
wdgt->setLayout(layout);
wdgt->setFixedSize(800,600);
wdgt->show();
return a.exec();
}
是的,您的代码会泄漏内存,因为您使用 new
创建对象而没有使用 Qt 的内存管理。
争取
QApplication a(argc, argv);
QWidget * wdgt = new QWidget(&app);
QVBoxLayout *layout = new QVBoxLayout(wdgt); // optional, setLayout does that
QFrame * frame = new QFrame(layout); // optional, addWidget does that
使用 Qt 的内存管理。
或者您可以使用 C++11 共享指针:
QApplication a(argc, argv);
std::shared_ptr<QWidget> wdgt = std::make_shared<QWidget>();
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
一旦共享指针的最后一个用户超出范围,您的对象就会自动删除。
看到这个post:Creating and deallocating a Qt widget object
说明如果一个Qtobject有一个parent,parent销毁时会自动删除
在您的代码中:
wdgt
是 layout
的 parent 因为你做了 wdgt->setLayout(layout)
.
wdgt
是 frame
的 parent 因为你做了 layout->addWidget(frame)
而 layout
的 parent 是 wdgt
.正如 thuga 所评论的那样,layout 将所有权传递给了他们自己的 parent。
在您的代码中,只有 wdgt
是孤立的(没有 Qt parent 自动删除它)。
要解决这个问题,您可以给他 parent:
QWidget * wdgt = new QWidget(&app);
因此wdgt
是app
的child,然后在app
被销毁时自动删除。
或者自己删除:
int main(int argc, char *argv[])
{
...
int res = a.exec();
delete wdgt; // this will delete wdgt, but also frame and layout
return res;
}
或者,最后,将其创建为 object,以便在超出范围时将其删除:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget wdgt;
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
frame->setLineWidth(5);
layout->addWidget(frame);
wdgt.setLayout(layout);
wdgt.setFixedSize(800,600);
wdgt.show();
return a.exec();
}
顺便说一下,如果你做了QVBoxLayout *layout = new QVBoxLayout(wdgt)
,就没有必要做wdgt->setLayout(layout)
了。所以这两段代码是等价的:
QVBoxLayout *layout = new QVBoxLayout(wdgt); // parenting upon construction
等同于:
QVBoxLayout *layout = new QVBoxLayout; // no parent
wdgt->setLayout( layout ); // reparenting
您的代码会泄漏内存,但首先您不应该编写甚至不得不关心资源泄漏的代码。让编译器帮你处理:
// main.cpp
#include <QtWidgets>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget widget;
QVBoxLayout layout(&widget);
QFrame frame;
frame.setFrameStyle(QFrame::Panel | QFrame::Plain);
frame.setLineWidth(5);
layout.addWidget(&frame);
widget.setFixedSize(800,600);
widget.show();
return a.exec();
}
我终于安装了 Ubuntu 并设置了 Qt+Valgrind 以防止内存泄漏,这是我在 Windows 中无法做到的。所以我不明白这段代码是否会导致内存泄漏?事实上,Valgrind 说我只有 500 多个问题,但与泄漏无关。我
#include <QWidget>
#include <QFrame>
#include <QVBoxLayout>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget * wdgt = new QWidget; //this line should be the cause of leakage
//if it exist (as far as i know)
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
frame->setLineWidth(5);
layout->addWidget(frame);
wdgt->setLayout(layout);
wdgt->setFixedSize(800,600);
wdgt->show();
return a.exec();
}
是的,您的代码会泄漏内存,因为您使用 new
创建对象而没有使用 Qt 的内存管理。
争取
QApplication a(argc, argv);
QWidget * wdgt = new QWidget(&app);
QVBoxLayout *layout = new QVBoxLayout(wdgt); // optional, setLayout does that
QFrame * frame = new QFrame(layout); // optional, addWidget does that
使用 Qt 的内存管理。
或者您可以使用 C++11 共享指针:
QApplication a(argc, argv);
std::shared_ptr<QWidget> wdgt = std::make_shared<QWidget>();
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
一旦共享指针的最后一个用户超出范围,您的对象就会自动删除。
看到这个post:Creating and deallocating a Qt widget object
说明如果一个Qtobject有一个parent,parent销毁时会自动删除
在您的代码中:
wdgt
是layout
的 parent 因为你做了wdgt->setLayout(layout)
.wdgt
是frame
的 parent 因为你做了layout->addWidget(frame)
而layout
的 parent 是wdgt
.正如 thuga 所评论的那样,layout 将所有权传递给了他们自己的 parent。
在您的代码中,只有 wdgt
是孤立的(没有 Qt parent 自动删除它)。
要解决这个问题,您可以给他 parent:
QWidget * wdgt = new QWidget(&app);
因此wdgt
是app
的child,然后在app
被销毁时自动删除。
或者自己删除:
int main(int argc, char *argv[])
{
...
int res = a.exec();
delete wdgt; // this will delete wdgt, but also frame and layout
return res;
}
或者,最后,将其创建为 object,以便在超出范围时将其删除:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget wdgt;
QVBoxLayout *layout = new QVBoxLayout;
QFrame * frame = new QFrame;
frame->setFrameStyle(QFrame::Panel | QFrame::Plain);
frame->setLineWidth(5);
layout->addWidget(frame);
wdgt.setLayout(layout);
wdgt.setFixedSize(800,600);
wdgt.show();
return a.exec();
}
顺便说一下,如果你做了QVBoxLayout *layout = new QVBoxLayout(wdgt)
,就没有必要做wdgt->setLayout(layout)
了。所以这两段代码是等价的:
QVBoxLayout *layout = new QVBoxLayout(wdgt); // parenting upon construction
等同于:
QVBoxLayout *layout = new QVBoxLayout; // no parent
wdgt->setLayout( layout ); // reparenting
您的代码会泄漏内存,但首先您不应该编写甚至不得不关心资源泄漏的代码。让编译器帮你处理:
// main.cpp
#include <QtWidgets>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget widget;
QVBoxLayout layout(&widget);
QFrame frame;
frame.setFrameStyle(QFrame::Panel | QFrame::Plain);
frame.setLineWidth(5);
layout.addWidget(&frame);
widget.setFixedSize(800,600);
widget.show();
return a.exec();
}