探索QTableWidget对单元格(QWidget/QTableWidgetItem)的内存管理[clearContents()]

简介: 1.clearContents() 会清除表格中的所有单元格内容,包括释放之前创建的QTableWidgetItem和通过 setCellWidget() 设置的 QWidget 对象,但是不指向nullptr并且是延时释放QWidget 的而QTableWidgetItem 立即释放;2.使用 setItem 方法将一个 QTableWidgetItem 对象设置为表格中的一个单元格后,该对象的位置(即所在行的索引)不会改变。这意味着,如果之后将该对象设置为其他单元格,它的位置将保持不变;3.而使用 setCellWidget 方法将一个QWidget对象设置单元格时,位置可能会改变

现象

memory.gif

结论

  1. clearContents() 会清除表格中的所有单元格内容,包括释放之前创建的 QTableWidgetItem 和通过 setCellWidget() 设置的 QWidget 对象,但是不指向nullptr并且是延时释放QWidget 的而QTableWidgetItem 立即释放;
  2. 使用 setItem 方法将一个 QTableWidgetItem 对象设置为表格中的一个单元格后,该对象的位置(即所在行的索引)不会改变。这意味着,如果之后将该对象设置为其他单元格,它的位置将保持不变;
原因:QTableWidgetItem 对象是动态地与表格的行和列关联的。当使用 setItem 方法将一个 QTableWidgetItem 对象设置为某个单元格时,该对象的位置将保持不变,因为它是与该单元格关联的
  1. 而使用 setCellWidget 方法将一个 QWidget 对象设置为表格中的一个单元格时,该对象的位置可能会改变;
原因: QWidget 对象不是直接与表格的行和列关联的,而是与 QTableWidget 对象本身关联的。
  • 总的来说:

QTableWidgetItem 对象与表格的行和列关联,而 QWidget 对象与整个表格本身关联。因此,当更改单元格中的 QTableWidgetItem 对象时,该对象的位置将保持不变;而当更改单元格中的 QWidget 对象时,该对象的位置将根据设置的单元格位置而改变。

  • 官方开发文档

image.png

代码验证clearContents() 会释放QTableWidgetItem 和QWidget 对象,但是不指向nullptr

memorytable.h


#ifndef MEMORYTABLE_H
#define MEMORYTABLE_H

#include <QWidget>
#include <QCheckBox>
#include <QTableWidgetItem>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MemoryTable; }
QT_END_NAMESPACE

class MemoryTable : public QWidget

{
    Q_OBJECT

public:
    MemoryTable(QWidget *parent = nullptr);
    ~MemoryTable();

private slots:
    void on_btnAdd_clicked();

    void on_btnClear_clicked();

private:
    Ui::MemoryTable *ui;
    QCheckBox*m_pQCheckBox=nullptr;
    QTableWidgetItem *m_pItem=nullptr;
};

#endif // MEMORYTABLE_H

memorytable.cpp


#include "memorytable.h"
#include "ui_memorytable.h"
#pragma execution_character_set("utf-8")

MemoryTable::MemoryTable(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MemoryTable)
{
    ui->setupUi(this);
    this->setWindowFlag(Qt::WindowStaysOnTopHint);
    ui->tableWidget->horizontalHeader()->setSectionResizeMode(
        QHeaderView::Stretch);

}

MemoryTable::~MemoryTable()
{
    delete ui;
}



void MemoryTable::on_btnAdd_clicked()
{
    if(m_pQCheckBox==nullptr){
        m_pQCheckBox=new QCheckBox();
        m_pQCheckBox->setCheckState(Qt::Checked);
    }
    if(m_pItem==nullptr){
        m_pItem=new QTableWidgetItem();
        m_pItem->setText("QTableWidgetItem 不为空");
    }

    auto state =m_pQCheckBox->checkState();

    QString text =m_pItem->text();

    int rowCount=ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(rowCount);

    ui->tableWidget->setCellWidget(rowCount,0,m_pQCheckBox);
    ui->tableWidget->setItem(rowCount,1,m_pItem);

    int curRow =m_pItem->row();  //curRow 一直
}


void MemoryTable::on_btnClear_clicked()
{
    ui->tableWidget->clearContents();

    //ui->tableWidget->setRowCount(0);
}

断点情况

image.png

验证clearContents()是延时释放QWidget 的而QTableWidgetItem 立即释放

  • 直接在clearContents() 后加上delete m_pQCheckBox不报错(重复删除(delete)同一个指针是不允许的)
  • 而 delete m_pItem或者访问m_pItem就会崩溃;(打断点/qDebug()就知道崩溃点了)
void MemoryTable::on_btnClear_clicked()
{
    ui->tableWidget->clearContents();
    
    auto state =m_pQCheckBox->checkState();    //不会崩溃
    qDebug()<<"state"<<state;
    delete m_pQCheckBox;                    //不会崩溃
    m_pQCheckBox = nullptr;
    
    QString text =m_pItem->text();            //会崩溃
    //ui->tableWidget->setRowCount(0);
}
相关文章
QString格式化的几种用法:补零/进制转换/保留小数位等
QString格式化的几种用法:补零/进制转换/保留小数位等
3159 0
|
安全 编译器 开发者
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式
581 0
|
存储 C++ 容器
(3)Qt中的变体数据类型(QVariant)
QVariant是Qt中一个强大的变体数据类型,能够存储和管理多种Qt和C++基本数据类型,包括自定义类型,并通过setValue()和value()方法进行赋值和取值。
688 9
(3)Qt中的变体数据类型(QVariant)
|
索引
【Qt 学习笔记】Qt常用控件 | 多元素控件 | List Widget的说明及介绍
【Qt 学习笔记】Qt常用控件 | 多元素控件 | List Widget的说明及介绍
1127 3
|
11月前
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
697 7
|
缓存 Linux C++
map异常崩溃分析汇总
文章讨论了std::map和std::set在某些情况下崩溃的原因,包括结构体字节对齐问题、多线程资源同步问题、以及比较器的实现问题,并提供了相应的解决方案。
350 0
【Qt 学习笔记】Qt窗口 | 标准对话框 | 颜色对话框QColorDialog
【Qt 学习笔记】Qt窗口 | 标准对话框 | 颜色对话框QColorDialog
2023 3
|
数据安全/隐私保护
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Line Edit的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Line Edit的使用及说明
1724 0
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Text Edit的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Text Edit的使用及说明
1628 0
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明
【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明
798 0