提问人:Juan Diego Monroy 提问时间:2/16/2023 最后编辑:Juan Diego Monroy 更新时间:2/17/2023 访问量:105
查询并不意味着是复制的。请改用移动构造
query is not mean to be a copied. Use move construction instead
问:
我一直在做一个代码,其中数据库纵,元素被 Qsqlite 数据库和查询保存和编辑,所以我使用的方式是按参数传递查询我不知道它有多糟糕,但每次它通过参数我都会收到这个警告:“ QSqlQuery 已弃用:并不意味着要复制: 改用移动构造“,我想知道正确的方法,我展示了 MainWindow 构造函数(警告在主中指示)。
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();
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());
}
//query.prepare("DELETE FROM articulo WHERE = 1");
//query.addBindValue("");
"Warning is here: " id = imprimirArticulos(query);
"Warning is here: " QObject::connect(ui->registrarBtn, &QPushButton::clicked, this, [=]()->void{registrarArticulo(query); });
QObject::connect(ui->addImagenBtn, &QPushButton::clicked, this, [=]()->void{subirFoto();});
"Warning is here: " QObject::connect(ui->buscarBtn, &QPushButton::clicked, this, [=]()->void{filtroArticulos(query);});
"Warning is here: " imprimirCategorias(query);
"Warning is here: " QObject::connect(ui->categoriasCBox, &QComboBox::currentIndexChanged, this, [=]()->void{agregarCategorias(query);});
model->setQuery(std::move(query));
}
答:
他们只想让对象移动,所以只存在一个查询。QSqlQuery
id = imprimirArticulos(query) //creates copy of query
您需要做的是移动:query
id = imprimirArticulos(std::move(query))
如果您在移动后再次尝试使用,它将是未定义的行为,因此您必须将其从函数移回 main 才能再次使用它。query
imprimirCategorias
评论
std::move()
query
query
query
std::move()
query
std::move()
std::move()
扩展 fg 的答案并编辑:当您调用按值传递对象的函数时,编译器会复制它(就像它对任何堆栈分配的对象所做的那样)。像往常一样,复制的确切类型取决于类的复制构造函数。对于这个类,它似乎是一个浅层的副本。因此,当对象具有关联的资源时(例如,当您准备查询并与之关联的绑定变量时),所有实例(原始实例和每个函数使用的副本)都将指向相同的“内部”资源。如果(且仅当)您在 的一个实例中更改某些内容时,这可能会导致问题,从而影响其他实例。query
query
query
情况并不完全相同,但您可以在这里阅读:https://doc.qt.io/qt-6/qsqlquery-obsolete.html
QSqlQuery无法有意义地复制。准备好的语句,装订 值等将无法正常工作,具体取决于您的数据库 驱动程序(例如,更改副本将影响原始副本)。 将QSqlQuery视为仅移动类型。
使用 时,可以得到一个 的 “xvalue 表达式”,可以直接传递给某些库重载。这些重载实际上是移动构造函数(并且,因为它们“可能假定参数是对对象的唯一引用”,所以它们很可能会“窃取”对象的内容,从而处于“未定义的行为”状态,调用函数不再可用)。请参见:https://en.cppreference.com/w/cpp/utility/movestd::move(query)
query
query
这里的关键点是:如果对象没有被修改(在你的主代码或被调用的函数中),你可以:a)只是关闭警告并保持代码不变;或 b) 为每个调用使用并创建一个新对象。你不能(你不应该)在调用它后重用它。相反,如果您确实修改了对象(可能在其中一个函数中),则唯一的选择是创建单独的实例。query
std::move()
query
query
std::move()
query
评论
std::move()
评论