我一直在做一个代码,其中数据库被操纵,元素被保存和编辑的Qsqlite数据库和查询,所以我一直使用的方式是通过参数传递查询我不知道它有多糟糕,但每次它通过参数我得到这个警告:“不推荐使用QSqlQuery:并不意味着可以复制:使用移动构造代替”,我想知道正确的方法,我显示了MainWindow构造函数,(警告在main中指出)。
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));
}
2条答案
按热度按时间0g0grzrc1#
他们只想移动
QSqlQuery
对象,这样就只存在一个查询。您需要做的是移动
query
:如果你在移动后再次尝试使用
query
,它将是未定义的行为,所以你必须将它从function移回main,以便在imprimirCategorias
中再次使用它。2guxujil2#
对fg的回答进行了扩展并编辑了:当你调用一个传递
query
对象的函数时,编译器会复制它(就像它对任何堆栈分配对象所做的那样)。复制的确切类型通常取决于类的 * 复制构造函数 *。对于此类,它似乎是一个浅复制。因此,当query
对象具有关联的资源时(例如,当你 * 准备 * 查询和与之关联的绑定变量时),所有的示例(原始的和每个函数使用的副本)将指向相同的“内部”资源,当(且仅当)你改变query
的一个示例中的某些内容,影响其他示例时,这可能会导致问题。这并不完全是同一个案例,但你可以在这里读到:https://doc.qt.io/qt-6/qsqlquery-obsolete.html
无法有意义地复制QSqlQuery。根据数据库驱动程序的不同,预准备语句、绑定值等将无法正常工作(例如,更改副本将影响原始副本)。请将QSqlQuery视为仅移动类型。
当使用
std::move(query)
时,您获得query
的“xvalue表达式”,它可以直接传递给一些库重载。这些重载实际上是 *move构造函数 *(并且因为它们 “可能假定自变量是对对象的唯一引用”,所以它们将很可能“窃取”对象的内容,使query
处于“未定义行为”状态,调用函数不再可用)。请参见:https://en.cppreference.com/w/cpp/utility/move这里的关键点是:如果
query
对象未被修改(在主代码或被调用函数中),您可以:a)撤销警告并保持代码不变;或者B)使用std::move()
并为每次调用创建一个新的query
对象。在调用std::move()
之后,您不能(不应该)重用原来的query
。相反,如果您确实修改了query
对象(可能在其中一个函数内部),您唯一的选择就是创建单独的示例。