默认移动构造函数

时间:2016-08-25 11:00:59

标签: c++ gcc4.8

我有一个数据库类,显式构造函数尝试根据传入的标志连接到数据库,如果失败则抛出。这不是所希望的(数据库可能不是由另一个应用程序创建的)所以我添加了一个空白构造函数和默认移动构造函数。在实用程序类中,我等到创建数据库并移入新数据库。

在单元测试中,我看到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_;
};

1 个答案:

答案 0 :(得分:2)

默认移动构造函数会移动所有内容。

然而database_是指针。指针移动实际上是复制。

然后在析构函数中,database_将被删除。

因为“旧”和“新”对象的database_都指向相同的内存位置,“新”对象将处于非稳定状态,因为database_将指向超空间。

如果你可以将database_改为智能指针,那么默认的移动构造函数就可以正常工作。

或者,创建自己的移动构造函数来移动所有内容,并将database_设置为nullptr,将connected_设置为false