QStandardItemModel内存管理

来源:互联网 发布:试戴墨镜软件 编辑:程序博客网 时间:2024/05/21 18:49

    参考资料[2]已经对如何结合QTreeViewQStandardItemModel创建一个树形结构做了很详细的说明,本文不再赘言。本文的主要目的是描述在编程过程中遇到的问题。

1 问题   

     在参考资料[2]中,为QStandardItemModel添加Item时,使用到下面的代码片段:

QList<QStandardItem *> items; for (int i = 0; i < 3; ++i) { QStandardItem *item = new QStandardItem(QString("item %0").arg(i));if (0 == i) item->setCheckable(true); items.push_back(item); } goodsModel->appendRow(items);

    从上述的代码中可见,每创建一个item,就需要使用new分配一次内存。(1)那么,在销毁QStandardItemModel的对象之前,是不是需要使用delete先将其各个item所占用的内存释放掉呢?正如参考资料[6]所提出的疑问那样。(2)另外,参考资料[8]也提出疑问,调用 clear()之后是否会释放QStandardItemModel所有Item的内存呢?(3)调用remoeRow()删除一行时,是否也会同时释放这一行所占用的内存呢?

2 实验

    根据参考资料[7]的指出,QStandardItemModel会获取Item的所有权,因此在销毁时同时释放各个Item的内存, 然而View并没有获取QStandardItemModel的所有权(因为同一个Model可以被多个View使用),因此需要程序员手工释放QStandardItemModel对象内存;参考资料[8]则指出,当调用clear()之后,所有item的内存都会被释放。

    上述的说法是否正确呢?下面做一个测试。

    根据参考资料[2]创建一个棵简单的树

<pre name="code" class="cpp">MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::MainWindow){    ui->setupUi(this);    goodsModel = new QStandardItemModel(0, 3, this);    ui->treeView->setColumnWidth(0, 50);    ui->treeView->setColumnWidth(1, 200);    ui->treeView->setColumnWidth(2, 200);    ui->treeView->setColumnWidth(3, 200);    goodsModel->setHeaderData(0, Qt::Horizontal, tr("No"));    goodsModel->setHeaderData(1, Qt::Horizontal, tr("name"));    goodsModel->setHeaderData(2, Qt::Horizontal, tr("value1"));    ui->treeView->setModel( goodsModel );    QList<QStandardItem *> items;    for (int i = 0; i < 3; ++i) {            QStandardItem *item = new QStandardItem(QString("item %0").arg(i));            if (0 == i)                item->setCheckable(true);            items.push_back( item );    }    goodsModel->appendRow( items );    // 释放Items内存    // delete goodsModel;     // goodsModel = NULL;        // 避免在析构函数中再次释放内存    // goodsModel->removeRow(0); // 删除第0行    // goodsModel->clear();      // 清空Model    // 尝试访问Items的内存    for (int i = 0; i < items.length(); i++) {        qDebug() << items.at(i)->column();    }}
    效果如下图(证明创建树成功):

                             图 1

    若是将上述代码中下述语句的前面两行或者第3第4行的其中一行

    // 释放Items内存    // delete goodsModel;     // goodsModel = NULL;        // 避免在析构函数中再次释放内存    // goodsModel->removeRow(0); // 删除第0行    // goodsModel->clear();      // 清空Model

   这时候再编译运行则提示:

程序异常结束。

    出现这个异常,主要是因为delete goodsModel,removeRow(0)或者clear()都会导致Moel释放Item的内存,下面语句尝试继续访问Item的内存时,产生非法内存访问

    // 尝试访问Items的内存    for (int i = 0; i < items.length(); i++) {        qDebug() << items.at(i)->column();    }
    如果将上面的代码片段注释掉,则不会出现程序异常结束的情况,但是所创建的树是空的


                     图 2 goodsModel->removeRow(0)的结果



                图3 goodsModel->clear() / delete goodsModel的结果

    上述实验验证了参考资料[7][8]的说法是正确的。同时也回答了第1章的第3个问题:removeRow()也会导致内存的释放。

    然而,正如参考资料[8]所指出的那样,QList是不会自动释放添加到其中的指针变量的(详细释放方法见参考资料[11]),唯有将各个Item添加到QStandardItemModel之后,QStandardItemModel才为它们管理内存。

参考资料

[1]QT中树控件QTreeView开发实例

[2]Qt TreeView

[3]Qt中如何自定义ListView/TreeView单个item的显示和响应

[5]Qt树形控件QTreeView使用1——节点的添加删除操作 复选框的设置

[6]Qt: Does this constitute a memory leak or not?

[7]Memory Management in Qt

[8]QStandardItemModel with QStandardItem usage

[9]Qt: QStandardItemModel的极品提示

[10]QStandardItemModel角色控制及QTreeView添加不同的右键菜单

[11]QList类介绍以及QList的内存释放

0 0
原创粉丝点击