qt中new与delete使用示例

qt中有时候使用new后并没有使用delete,原因是

Qt 自动回收是靠父子关系。父亲销毁了。他的孩子也销毁。

delete(Qobject* obj)//有时需要手动销毁

delete(this);    //delete this;

#include "mainwindow.h"
#include <QApplication>
#include <QTextCodec>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    QLabel *label =new QLabel("hello",&w);
    //这里使用new之后不需要执行delete,因为label的父类是w,而w是在栈中创建,在程序关闭的时候会自动释放,所以作为w的子类内存也被释放。

    QLabel *label1 =new QLabel("world");
    //这个是需要执行delete label1,否则会造成内存泄漏,因为label没有父类,所以不会为label释放内存
    w.show();
    a.exec();
    delete label1;
    label1=NULL;
    return 0;
}

 

总的来说,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中的对象了。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值