0

我总是使用下面的代码连接到 sqlite 数据库。由于某些原因,我决定以使用*QSqlDatabase而不是QSqlDatabase.

我所做的只是在我的旧代码( Line_12&前面使用。但代码在第 6 行崩溃。

无论如何,有人给了我line_14并且它有效。

所以......我不明白我的第一个代码有什么问题以及为什么建议的代码使它工作。

Foo::Foo(QString path_="db_path_name") {
    InitialDataBase(path_);
    bool isOpened = db->open();
    if(!isOpened)   exit(1);
    else            
        queryExecutor = new QSqlQuery(*db);  // --> Line_6
}

void Foo::InitialDataBase(QString path_) {

    // Line_12 => DOESN'T WORK
    db = &(QSqlDatabase::addDatabase("QSQLITE"));   
    // Line_14 => WORK
    db  = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"));

    db->setHostName("localhost");
    db->setDatabaseName(path_);
    db->setUserName("admin");
    db->setPassword("admin");
}
4

1 回答 1

0

在第 12 行中,您将获取由返回的 QSqlDatabase 对象的地址addDatabase()。该对象是临时的,并在语句结束后(第 12 行之后)立即销毁。因此,您最终会得到一个悬空指针,即指向已删除对象的指针。取消引用悬空指针是未定义的行为。在实践中,它通常会崩溃。

在第 14 行,在堆上创建了一个新的 QSqlDatabase 对象,创建了从 addDatabase() 返回的临时 QSqlDatabase 对象的副本。复制构造函数 QSqlDatabase(const QSqlDatabase&) 在这里被调用。临时对象被销毁,但堆上的副本仍然存在。请注意,您必须db稍后删除,否则最终会导致内存和资源泄漏(打开数据库连接)。

你为什么在这里使用指针?尤其是作为初学者,它只会导致崩溃和泄漏,如本例所示;)

于 2014-03-14T08:12:37.023 回答