总的来说,Qt的对象如果使用new声明为指针,那么:(1)如果它没有父对象,
可以在不需要的使用使用delete把它释放。(2)如果它有父对象,会在父对象
销毁的时候同时被销毁。父对象什么时候销毁参见第一条。下面是一些例子。
1、使用delete
这个例子如下
//第一个程序
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
label->setText("first line\nsecond line");
label->setAlignment(Qt::AlignBottom | Qt::AlignRight);
label->show();
return app.exec();
}
//第二个程序
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
label->setText("first line\nsecond line");
label->setAlignment(Qt::AlignBottom | Qt::AlignRight);
label->show();
int ret = app.exec();
//释放内存
delete label;
return ret;
}
因为label没有父对象,所以它的释放只能自己来。第一个程序没有释放内存。
第二个程序使用了delete释放了内存。
2、使用标志位
使用标志位可以不显示的使用delete,但和使用delete是一样的。因为Qt在暗中
使用了delete。
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setAttribute(Qt::WA_DeleteOnClose);
label->setText("first line\nsecond line");
label->show();
return app.exec();
}
下面是一个暗中使用delete的例子。这是一个类,它有一个成员函数,可以删除
自己。当然只能删除由关键字new创建的自己。
#include<iostream>
using namespace std;
//类AAA
class AAA
{
public:
//构造函数
AAA();
~AAA(void);
void delete_me(void);
};
//构造函数
AAA::AAA(void)
{
//空的
}
//析构函数
AAA::~AAA(void)
{
//空的
}
//删除自己
void AAA::delete_me(void)
{
delete this;
}
int main(void)
{
AAA *a = new AAA;
cout<<"point a will be deleted by himself."<<endl;
a->delete_me();
cout<<"point a has been deleted."<<endl;
return 0;
}
3、依靠父对象
下面是第二种情况。例子如下
#include <QApplication>
#include <QWidget>
#include <QPushButton>
//自定义类
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
~MyWidget();
};
//构造函数
MyWidget::MyWidget(QWidget *parent):QWidget(parent)
{
setMinimumSize(200,120);
setMaximumSize(200,120);
QPushButton *quit = new QPushButton("quit",this);
quit->setGeometry(62,40,75,30);
}
//析构函数
MyWidget::~MyWidget()
{
//不用做什么
}
//主函数
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget w;
w.setGeometry(100,100,200,120);
w.show();
return app.exec();
}
这个例子中有一个“QPushButton”类型的指针“quit”,它有父对象。所以它随着
父对象一起销毁。不需要担心内存的问题。实际上是Qt帮忙解决了。
4、声明为变量的风险
下面是一个错误的例子,它可以编译成可执行文件,但它会在程序结束时崩溃
#include <QApplication>
#include <QWidget>
#include <QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QLabel label("Hello Qt!");
QWidget w;
label.setParent(&w);
w.show();
return app.exec();
}
因为退出时,w比label先被析构,当w被析构时,会删除chilren列表中的对象,
也就是这儿的label。但label却不是通过new分配在heap中,而是在stack中,可
想而知,delete一个再stack中的对象会怎么样了。下面的程序是正确的
#include <QApplication>
#include <QWidget>
#include <QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QWidget w;
QLabel label("Hello Qt!");
label.setParent(&w);
w.show();
return app.exec();
}
这个程序仅仅是声明变量的时候换了个顺序。于是运行正确了。这样可以确保
label先于其parent被析构。这样label析构时将自己从父对象的列表中移除自己,
w析构时,children列表中就不会有分配在stack中的对象了。
可以在不需要的使用使用delete把它释放。(2)如果它有父对象,会在父对象
销毁的时候同时被销毁。父对象什么时候销毁参见第一条。下面是一些例子。
1、使用delete
这个例子如下
//第一个程序
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
label->setText("first line\nsecond line");
label->setAlignment(Qt::AlignBottom | Qt::AlignRight);
label->show();
return app.exec();
}
//第二个程序
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
label->setText("first line\nsecond line");
label->setAlignment(Qt::AlignBottom | Qt::AlignRight);
label->show();
int ret = app.exec();
//释放内存
delete label;
return ret;
}
因为label没有父对象,所以它的释放只能自己来。第一个程序没有释放内存。
第二个程序使用了delete释放了内存。
2、使用标志位
使用标志位可以不显示的使用delete,但和使用delete是一样的。因为Qt在暗中
使用了delete。
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel;
label->setAttribute(Qt::WA_DeleteOnClose);
label->setText("first line\nsecond line");
label->show();
return app.exec();
}
下面是一个暗中使用delete的例子。这是一个类,它有一个成员函数,可以删除
自己。当然只能删除由关键字new创建的自己。
#include<iostream>
using namespace std;
//类AAA
class AAA
{
public:
//构造函数
AAA();
~AAA(void);
void delete_me(void);
};
//构造函数
AAA::AAA(void)
{
//空的
}
//析构函数
AAA::~AAA(void)
{
//空的
}
//删除自己
void AAA::delete_me(void)
{
delete this;
}
int main(void)
{
AAA *a = new AAA;
cout<<"point a will be deleted by himself."<<endl;
a->delete_me();
cout<<"point a has been deleted."<<endl;
return 0;
}
3、依靠父对象
下面是第二种情况。例子如下
#include <QApplication>
#include <QWidget>
#include <QPushButton>
//自定义类
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
~MyWidget();
};
//构造函数
MyWidget::MyWidget(QWidget *parent):QWidget(parent)
{
setMinimumSize(200,120);
setMaximumSize(200,120);
QPushButton *quit = new QPushButton("quit",this);
quit->setGeometry(62,40,75,30);
}
//析构函数
MyWidget::~MyWidget()
{
//不用做什么
}
//主函数
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget w;
w.setGeometry(100,100,200,120);
w.show();
return app.exec();
}
这个例子中有一个“QPushButton”类型的指针“quit”,它有父对象。所以它随着
父对象一起销毁。不需要担心内存的问题。实际上是Qt帮忙解决了。
4、声明为变量的风险
下面是一个错误的例子,它可以编译成可执行文件,但它会在程序结束时崩溃
#include <QApplication>
#include <QWidget>
#include <QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QLabel label("Hello Qt!");
QWidget w;
label.setParent(&w);
w.show();
return app.exec();
}
因为退出时,w比label先被析构,当w被析构时,会删除chilren列表中的对象,
也就是这儿的label。但label却不是通过new分配在heap中,而是在stack中,可
想而知,delete一个再stack中的对象会怎么样了。下面的程序是正确的
#include <QApplication>
#include <QWidget>
#include <QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QWidget w;
QLabel label("Hello Qt!");
label.setParent(&w);
w.show();
return app.exec();
}
这个程序仅仅是声明变量的时候换了个顺序。于是运行正确了。这样可以确保
label先于其parent被析构。这样label析构时将自己从父对象的列表中移除自己,
w析构时,children列表中就不会有分配在stack中的对象了。