QSqlQuery拷贝警告问题:如何改用移动构造传递参数?
在Qt中基于SQLite编写数据保存与编辑代码时,传递QSqlQuery对象会触发警告:QSqlQuery is deprecated: is not mean to be copied: use move construction instead,下面结合你的代码给出正确实现方式。
问题原因
QSqlQuery的拷贝构造函数已被标记为废弃,因为它内部持有数据库连接、查询状态等资源,直接拷贝会导致资源管理冲突,Qt官方推荐使用移动语义或者避免传递QSqlQuery实例,改为在需要的地方创建独立的QSqlQuery对象。
推荐解决方案:避免传递QSqlQuery,函数内部创建实例
这种方式更安全,每个数据库操作使用独立的QSqlQuery,避免多个操作共享同一实例导致的状态混乱,同时彻底消除警告。
步骤1:修改相关函数,移除QSqlQuery参数
将imprimirArticulos、registrarArticulo、filtroArticulos、imprimirCategorias、agregarCategorias这些函数的参数中的QSqlQuery去掉,改为在函数内部基于类成员的db对象创建新的QSqlQuery:
示例(以imprimirArticulos为例):
int MainWindow::imprimirArticulos() { QSqlQuery query(db); // 使用类中已打开的db对象创建新query // 执行你的查询、数据处理逻辑 // ... return 0; // 返回你的id值 }
步骤2:修改构造函数中的调用与连接
去掉所有传递QSqlQuery的代码,直接调用无参函数,信号连接也改为直接绑定成员函数:
修改后的完整构造函数代码:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); char dirNow[1024]; db = QSqlDatabase::addDatabase("QSQLITE"); QString dirfull = QString(_getcwd(dirNow, 1024)) + "\\inventario.db"; db.setDatabaseName(dirfull); if(!db.open()){ qDebug() << db.lastError().text(); } model = new QSqlQueryModel(); // 临时query用于建表操作 QSqlQuery query(db); if(!query.exec("CREATE TABLE IF NOT EXISTS articulo (codigo INTEGER NOT NULL, nombre VARCHAR(55) NOT NULL, unidades INTEGER NOT NULL, " "categoria VARCHAR(55) NOT NULL, pais VARCHAR(55) NOT NULL, precio DOUBLE NOT NULL, foto VARCHAR(200) NOT NULL, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT) ")){ QMessageBox::information(this, "Error", query.lastError().text()); } if(!query.exec("CREATE TABLE IF NOT EXISTS categorias(valor VARCHAR(55) NOT NULL) ")){ QMessageBox::information(this, "Error", query.lastError().text()); } // 直接调用无参函数 id = imprimirArticulos(); // 信号连接直接绑定成员函数 QObject::connect(ui->registrarBtn, &QPushButton::clicked, this, &MainWindow::registrarArticulo); QObject::connect(ui->addImagenBtn, &QPushButton::clicked, this, &MainWindow::subirFoto); QObject::connect(ui->buscarBtn, &QPushButton::clicked, this, &MainWindow::filtroArticulos); imprimirCategorias(); QObject::connect(ui->categoriasCBox, &QComboBox::currentIndexChanged, this, &MainWindow::agregarCategorias); // 为QSqlQueryModel创建独立的query QSqlQuery modelQuery(db); modelQuery.exec("SELECT * FROM articulo"); // 替换为你需要的查询语句 model->setQuery(std::move(modelQuery)); }
备选方案:使用移动语义传递QSqlQuery(仅适合单次传递场景)
如果你确实需要传递QSqlQuery,可以使用std::move转移对象所有权,但要注意:一旦调用std::move,原QSqlQuery对象会处于无效状态,不能再被后续代码使用。
示例:
// 仅单次传递时使用 id = imprimirArticulos(std::move(query)); // 注意:此时原query对象已失效,不能再用于后续的imprimirCategorias等操作
显然这种方式不适合你当前的场景,因为你需要多次使用query对象,所以推荐第一种方案。
内容的提问来源于stack exchange,提问作者Juan Diego Monroy

