我有一个数据库类,显式构造函数尝试连接到基于传入的标志的数据库,如果失败则抛出。这是不希望的(数据库可能不是由另一个应用程序创建的),所以我添加了一个空构造函数和默认的移动构造函数。在工具类中,我一直等到数据库被创建并移动一个新的数据库。默认移动构造函数
在单元测试中,我看到database_utils::connected()
在移动之前返回false,在移动之后返回true。但是,如果我调用一个使用数据库的函数,我会得到一个library routine called out of sequence
错误。这表明我没有打开数据库或格式不正确的select语句,但构造函数和析构函数按照正确的顺序调用,并且在创建数据库,填充它和select语句工作的地方对数据库本身进行了单元测试。
所以我的问题:默认移动实际上是否移动它?如果不是,我需要做什么才能获得预期的行为?
示例代码:
class database
{
database() : connected_(false), database_(nullptr) { }
database(/* params */) : connected_(false), database_(nullptr) {
/* attempt connection, throw on fail */
connected_ = true;
}
database(database& other) = default;
database(database&& other) = default;
database& operator=(database&& other) = default;
~database() { /* clean up */ }
operator bool() const { return connected_; }
bool connected_;
sqlite3* database_;
};
class database_utils
{
database_utils() : db_() { }
void connect() {
db_ = std::move(database(/*params*/));
}
bool connected() { return db_; }
void example_select(/* params */) {
/* use db_ */
}
database db_;
};
如果您想验证您的移动构造函数正在被调用,请在其中添加一条调试语句,并查看它是否出来。您当然知道,默认构造函数中没有任何东西会使得从移动对象的指针(如'database_',这看起来像一个错误)变为空值。你需要编写自己的移动构造函数,这是正确的。 –
[OT]:复制构造函数通过const引用取其arg。 – Jarod42
您可能希望移动构造函数重置已移动的指针以避免双重清理。 – Jarod42