提问者:小点点

QFileSystemModel对象是否会被删除?


我有一个经典的QDialog,它用QFileSystemModel填充QTreeView,并具有过滤和处理用户选择项列表的功能。 我是一个完全的C++和Qt新手,所以我一直在学习大量的在线教程和示例。 代码最后看起来是这样的[内容匿名化,为简洁起见进行了编辑]:

在头文件中:

class MyExampleDialog : public QDialog
{
    Q_OBJECT

    public:
        explicit MyExampleDialog(MyMainWidget *parent = nullptr);
        ~MyExampleDialog();

    public slots:
        virtual void accept() override;

    private slots:
        void directoryPathEntered();
        void checkDirectoryPathAndUpdateTree(const QString& pathToCheck);
        void validateSelection();

    private:
        QString getDirectoryPath() const;
        QStringList updateFileSelection();

        Ui::MyExampleDialog *_ui;
};

在源文件中:

MyExampleDialog::MyExampleDialog(MyMainWidget *parent) :
    QDialog(parent),
    _ui(new Ui::MyExampleDialog)
{
    _ui->setupUi(this);
    _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    _ui->directoryPathEdit->setText(getDirectoryPath());
    checkDirectoryPathAndUpdateTree(getDirectoryPath());
    QObject::connect(_ui->browseButton, &QPushButton::pressed, this, &MyExampleDialog::directoryPathEntered);
    QObject::connect(_ui->directoryPathEdit, &QLineEdit::textChanged, this, &MyExampleDialog::checkDirectoryPathAndUpdateTree);
}

MyExampleDialog::~MyExampleDialog()
{
    delete _ui;
}

void MyExampleDialog::directoryPathEntered()
{
    const QString currentPath = getDirectoryPath();
    QString newPath = QFileDialog::getExistingDirectory(this, tr("Select the installation directory"), currentPath);
    if(newPath.isEmpty())
        return;

    _ui->directoryPathEdit->setText(newPath);
    // then write newPath to QSettings
}

QString MyExampleDialog::getDirectoryPath() const
{
    // retrieve path from QSettings
}

void MyExampleDialog::checkDirectoryPathAndUpdateTree(const QString& pathCheck)
{
    if(std::filesystem::exists(pathCheck.toStdString()+"/bin/config.xml"))
    {
        QStringList filters;
        filters << "*.jpeg";
        QFileSystemModel *model = new QFileSystemModel(this);
        model->setRootPath(pathCheck+QString::fromUtf8("/Images"));
        model->setReadOnly(true);
        model->setFilter(QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot);
        model->setNameFilters(filters);
        _ui->imgTreeView->setModel(model);
        _ui->imgTreeView->setRootIndex(model->setRootPath("/Images"));
        _ui->imgTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
        QObject::connect(_ui->imgTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MyExampleDialog::updateImgSelection);
        QObject::connect(_ui->imgTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MyExampleDialog::validateSelection);
    }
    else
    {
        if(pathCheck.isEmpty()) { }
        else
        {
            QMessageBox::critical(this, tr("Error"), tr("No config.xml file in installation /bin directory"));
        }
        _ui->imgTreeView->setModel(nullptr);
    }
}

QStringList MyExampleDialog::updateImgSelection()
{
    QItemSelectionModel *selModel = _ui->imgTreeView->selectionModel();
    QModelIndexList selIndices = selModel->selectedIndexes();
    QStringList imgSel;
    QFileSystemModel *fsModel = static_cast<QFileSystemModel*>(_ui->imgTreeView->model());

    foreach(QModelIndex index, selIndices)
    {
        // parse data to obtain file name
    }
    return imgSel;
}

void MyExampleDialog::validateSelection()
{
    QStringList imgList = updateImgSelection();
    if(! imgList.isEmpty())
    {
        _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
    }
    else { _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); }
}

void DataSolverDialog::accept()
{
    // do stuff when OK is clicked
}

注意,在函数CheckDirectoryPathanDupDateTree中,我们使用new声明了指向新QFileSystemModel对象的指针。 不能用此函数作用域中的delete删除此指针,因为我希望模型持久化,以便UpdateImgSelection可以使用它。 这似乎是QFileSystemModel对象的非常标准的用法,但是在C++中,我们被教导永远不要用new实例化对象而不随后使用delete释放内存。 我的问题是QFileSystemModel的这种用法是否会导致内存泄漏,如果是,如何避免?


共1个答案

匿名用户

欢迎来到C++和Qt的有趣世界。 你对“new”和“delete”的配对保持谨慎是正确的。 然而,Qt的引擎为您做了大量的对象管理。

简单的回答是:这不会导致内存泄漏

更长的简短回答:这不会导致内存泄漏。 您正在创建一个对象并告诉Qt该对象的父对象是'this'。 Qt现在将您的对象置于父子关系中,'this'是父对象,而您的新对象是子对象。 当删除父项时,子项也将随父项一起删除。

但是,请帮自己一个忙,花时间了解一下Qt如何处理对象,以及何时由您来照顾实例。 如果您不这样做,您可能会发现自己有非常令人沮丧的内存泄漏,看似随机的崩溃,或者“丢失”您认为应该存在的对象。

祝你好运,坚持下去。