【发布时间】:2015-05-13 08:44:46
【问题描述】:
我一直在用 Bjarne Stroustrup 的书 [C++ 11] 为我的论文学习 C++。即便如此,我仍然没有得到有关在 C++ 中处理内存泄漏的信息。他在书中说了很多以避免使用new、delete 以及自定义析构函数。
我想说我正在使用 QT 来构建我的 UI,现在请在我的前三个问题中考虑这个示例:
class KHUB : public QMainWindow
{
Q_OBJECT
public:
KHUB(QWidget *parent = 0)
{
createGroupScreen();
};
~KHUB();
private:
QWidget *groupScreen;
void createGroupScreen()
{
groupScreen = new QWidget();
};
}
这是恢复我的应用程序。我有一个名为 KHUB 的构造函数,它创建一个对话框 (QWidget),提供一些选项来放置名称、类别等,以创建一个新组。
既然我应该避免赤裸裸的
new和delete,有没有不同的方法(例如使用unique_ptr,不确定它是否是一个适用的概念)或者不太容易创建这个QWidget并且仍然有对象引用来在我的createGroupScreen成员函数之外对其进行操作?
1234563函数会被删除吗?
如果它在其父级中仍然存在,我如何在成员函数之外获取对象引用以便调用
~QWidget()?
我的第四个问题是关于同一个对象的破坏。
- 如果我通过调用
groupScreen->~QWidget()来破坏groupScreen,这只会破坏我的QWidget对象,并且我的指针将作为内存泄漏留在那里等待我去delete groupScreen?
考虑我的第五个、第六个和最后一个问题的另一段代码:
class KHUB : public QMainWindow
{
Q_OBJECT
public:
KHUB(QWidget *parent = 0)
~KHUB()
{
delete groupScreen;
delete buttonOne;
delete buttonTwo;
delete buttonThree;
};
private:
QWidget *groupScreen;
QPushButton *buttonOne, *buttonTwo, *buttonThree;
/* Components Setup */
void btSetup(QPushButton** button, const QString name, int posX, int posY, int width, int height);
}
我正在尝试使用具有设置按钮名称、位置和大小的功能的按钮来重用一些代码,因此通过对每个按钮重复输入相同的参数,代码不会变得如此之大 - 但我'我也担心节目的表现。
当我调用我的 KHUB 构造函数时,这并不意味着我的 .h 文件中的所有全局指针都被分配了,对吗?只有在初始化时才会发生这种情况,对吗?
如果我真的需要创建我的自定义析构函数,我应该删除在我的 .h 文件中声明的每个全局指针吗?我想知道如果我没有通过其中一个指针的初始化,这是否不会有风险。
有没有办法循环指针获取和删除?即
for(auto p : globalPtrs) delete p;
我试图在堆栈中找到一些关于这个主题的问题,但没有一个对我有真正的启发:
【问题讨论】:
-
我对内存泄漏的理解(我相信其他人会纠正我或有更好的信息)是你正在使用指针类扩展的任何对象。它们存在于内存或内存中早已存在它在范围内。内存泄漏来自范围内不必要的东西,它们都占用了内存空间。如果你不能使用删除,也许你可以将你正在使用的东西设置为 NULL。您正在使用的操作系统会神奇地处理新对象的内存分配。智能指针是一件事,顺便说一句,这对他们来说是一个很棒的心房umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
-
您应该尽可能使用
std::make_shared和std::make_unique,而不是将new的结果传递给智能指针构造函数。这就是也不直接使用new的意思。 -
最后,直接显式调用析构函数是相当罕见的。我刚刚浏览了我目前正在处理的一个 50k LOC 项目,并且在任何地方都没有一个显式的析构函数调用。你需要有一个很好的理由这样做,几乎。如果您不编写手动资源管理库代码,则可能不应该显式调用析构函数。
-
你也忘记了
QObject是一个智能指针集合(真的!)。QObject类似于std::vector<std::unique_ptr<QObject>>。QObject是一个智能指针,拥有其子项的唯一所有权。对拥有的QObjects 应用额外的内存管理层通常会适得其反。如果他们有父母,父母会担心他们。 -
最后,在父窗口小部件中存储指向子窗口小部件的唯一指针没有多大意义。孩子可以是简单的直接成员,而不是指针成员。
标签: c++ qt memory-leaks destructor