RAII和任务

时间:2010-07-18 01:13:56

标签: c++ raii assignment-operator

我为sqlite3连接创建了以下类:

class SqliteConnection
{
public:
    sqlite3* native;

    SqliteConnection (std::string path){
        sqlite3_open_v2 (path.c_str(), &native, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
    }

    ~SqliteConnection (){
        sqlite3_close(native);
    }
}

然后可以按如下方式初始化连接

SqliteConnection conn("./database.db");

但是,我希望能够共享此连接,将其存储为类中的成员等,并且问题在于默认赋值运算符operator=。做点什么

SqliteConnection conn("./database.db");
SqliteConnection conn1 = conn;
当每个变量超出范围时,

会导致对数据库指针进行两次sqlite3_close调用。当您需要将资源分配给不同的变量时,如何克服RAII的这一困难?

3 个答案:

答案 0 :(得分:9)

对于共享资源,您必须跟踪存在的对它们的引用,例如使用reference counting。一个实现是boost::shared_ptr,带有自定义删除器:

class SqliteConnection {
    boost::shared_ptr<sqlite3> native;
public:
    SqliteConnection(const std::string& path) 
      : native(init_connection(path), &destroy_connection)
    {}
    // ...
};

sqlite3* init_connection(const std::string& path) {
    // ...
    return ptr;
}

void destroy_connection(sqlite3* p) {
    sqlite3_close(p);
}

答案 1 :(得分:3)

将连接放在shared_ptr中。在分配时,您所要做的就是分配“shared_ptr”以拥有资源(连接)的共享所有权。否则,您必须为您的类实现已经在boost中完成的共享所有权,并且包含在C ++ 0x中。

答案 2 :(得分:0)

您有四个基本选项:

  • 可能通过shared_ptr使用引用计数。这是效率最低的,但它是最通用的解决方案。
  • 禁止分配。不允许用户复制SQLite对象。使赋值运算符和复制构造函数为私有。然后,用户将不得不传递指针或引用。
  • 让分配“偷”资源。这就是auto_ptr的作用。 a = b会导致a获得b的连接,并将b设置为空值,作为空的无法使用的对象。
  • 创建副本时创建新连接。这取决于提供必要功能的sqlite API。特别是,可能还必须复制查询和其他特定于连接的数据,这可能是不切实际的