【问题标题】:RAII and assignmentRAII 和分配
【发布时间】:2011-03-17 11:32:02
【问题描述】:

我为 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 克服这一困难?

【问题讨论】:

    标签: c++ raii assignment-operator


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      对于共享资源,您必须跟踪是否存在对它们的引用,例如使用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);
      }
      

      【讨论】:

      • 在您的回答中看起来像是一些额外的垃圾:, destroy_connection()) 行似乎不属于。
      【解决方案3】:

      您有四个基本选择:

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

      【讨论】:

      • 你已经命名了选项,但你也应该尝试指出哪些是合适的以及为什么。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多