在 Qt 上使用 std::unique_ptr

红Z

长期以来,我一直在使用旧的 C++ 进行编程,因为我和我的团队从未决定升级到现代编程实践(我承认,部分原因也是我的错),所以最近我一直在学习 C++11, C++14、C++17 所以我可以掌握它的窍门,我遇到的第一件事是 std::unique_ptr,在我看来它使用起来很棒,但我仍然对将它与 Qt 一起使用感到困惑,因为我在 Qt 中读到过,如果我创建一个 QObject,它是另一个 QObject 的子级,如果父级被删除,则子级也将被删除,并且使用 std::unique_ptr 可能会导致双重删除。所以我想知道,这是正确的:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSqlQueryModel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    QSqlDatabase p_AppDB;
    QSqlQueryModel *p_QueryModel;
};
#endif // MAINWINDOW_H

主窗口.cpp:

#include "MainWindow.h"
#include "ui_MainWindow.h"

#include "Dialog.h"

#include <QDebug>
#include <QSqlQuery>
#include <QSqlError>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    p_AppDB = QSqlDatabase::addDatabase("QSQLITE" , "test"); // Set Database connection driver + name
    p_AppDB.setDatabaseName("AppDB.db"); // Set SQLite database file name
    if(!p_AppDB.open()) // Open database and check if connection failed
    {
        qDebug() << "ERR: " << p_AppDB.lastError().text(); // Print out an error message
    }

    p_QueryModel = new QSqlQueryModel(this); // How do i avoid using 'new' here ?

    QSqlQuery _Query(QSqlDatabase::database("test")); // Create a new QSqlQuery
    _Query.prepare("SELECT * FROM Users"); // Prepare a simple query to select everything from the table 'user'
    if(!_Query.exec()) // Execute query and check if the execution failed
    {
        qDebug() << _Query.lastError().text(); // Print out an error message
        return; // Return if the execution failed
    }
    p_QueryModel->setQuery(_Query); // Set the QSqlQuery with its data to the QSqlQueryModel we created
    ui->View_TableView->setModel(p_QueryModel); // Set the QSqlQueryModel with its data to the TableView

    // TEST
    auto dlg = std::make_unique<Dialog>(); // Create a new Dialog
    dlg->exec(); // Execute (Display) the dialog
}

MainWindow::~MainWindow()
{
    p_AppDB.close(); // Close the database connection
    delete ui;
}

例如,在创建 QWidget 或其他任何东西时,我如何使用 std::unique_ptr 而不是使用旧的: QWidget *w = new QWidget(this);

我知道可能会出现一些错误,因为我已经有一段时间没有编程了,现在我又回到了 C++ 和 Qt,但我希望是否还有其他错误可以指出。

谢谢

杰里米·弗里斯纳

简短的回答是你不能——QWidget 父/子所有权方案和智能指针不能互操作。你是对的,试图用智能指针控制它们通常会导致双重删除问题。

在某些情况下,您可以执行类似的操作std::unique_ptr<QWidget> ptr(new QWidget);,并且QWidgetunique_ptr超出范围时对象将被删除,正如预期的那样 - 但 Qt 中的许多功能都基于遍历在您制作各种QWidget'时组装的对象树s 是 otherQWidget孩子,所以通过智能指针管理小部件只有在该小部件永远不需要成为任何其他小部件的孩子时才实用。

所以:在 Qt-land 中,像 Qt API 那样做,并在适当的情况下使用传统的父子所有权方法。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用 std::move 将 std::unique_ptr 作为 qt 信号参数传递

在QMainWindow上使用std :: unique_ptr时,退出时发生QT应用程序分段错误

C ++ Qt std :: unique_ptr Qt版本在哪里?

在 QVector<std::unique_ptr<Type>> 上使用 std::find

如何在结构上使用std :: unique_ptr?

使用std :: unique_ptr <T>&代替std :: unique_ptr <T>有什么优势吗?

使用什么std :: optional或std :: unique_ptr

使用 std::unique_ptr<T>::unique_ptr` 在 Visual Studio 2013 中构建错误

使用 std::unique_ptr 使用 CRTP 进行转换

如何在std :: copy中使用unique_ptr?

如何使用std:unique_ptr擦除包含结构的向量?

使用std :: unique_ptr创建对象数组

我应该使用QScopedPointer还是std :: unique_ptr?

使用std :: move(nullptr)的unique_ptr的operator =的C ++错误

使用std :: unique_ptr时出现内存泄漏

一些std :: unique_ptr使用和“陷阱”

使用 std::move 分配 unique_ptr 不起作用

使用地图内的std :: unique_ptr作为键

使用带有分配器的std :: unique_ptr

无法使用std :: unique_ptr初始化指针

使用std :: unique_ptr增强图形捆绑属性

const使用std :: unique_ptr / std :: shared_ptr正确合成

使用C ++ std :: unique_ptr <>或std :: shared_ptr <>来管理Objective-C对象

奇怪的错误:当未真正创建指针时,使用删除的函数'std :: unique_ptr <_Tp,_Dp> :: unique_ptr

在std :: unique_ptr的向量上使用make_transform_iterator获取const指针

使用`std :: unique_ptr`时`std :: vector`中的数据不同

使用std :: function对象将自定义删除器传递给std :: unique_ptr

C ++ std :: unique_ptr存储在std :: map内部,使用删除的函数会形成不良

是否可以使用fill构造函数创建std :: vector <std :: unique_ptr <Bar >>?