RAII 和分配

发布于 2024-09-10 07:58:45 字数 674 浏览 5 评论 0原文

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

I created the following class for an sqlite3 connection:

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);
    }
}

and then one can initialize a connection as follows

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

However, I would like to be able to share this connection, store it as a member in classes, etc., and the trouble is with the default assignment operator operator=. Doing something like

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

would lead to two sqlite3_close calls on the database pointer as each variable goes out of scope. How do you overcome this difficulty with RAII when you need to assign your resource to a different variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

本王不退位尔等都是臣 2024-09-17 07:58:45

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

For shared resources you will have to keep track of wether references to them exist, e.g. using reference counting. One implementation is boost::shared_ptr with a custom deleter:

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);
}
半﹌身腐败 2024-09-17 07:58:45

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

Put the connection in a shared_ptr. On assignment all what you have to do is to assign "shared_ptr"s to have shared ownership of the resource(connection). Otherwise you have to implement shared ownership for your class which already has been done in boost and is included in C++0x.

所有深爱都是秘密 2024-09-17 07:58:45

您有四个基本选项:

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

You have four basic options:

  • Use reference counting, probably through a shared_ptr. This is the least efficient, but it's the most general solution.
  • Prohibit assignments. Don't allow the user to copy the SQLite object. Make the assignment operator and copy constructors private. Then users will have to pass pointers or references around instead.
  • Let assignment "steal" the resource. This is what auto_ptr does. a = b results in a taking ownership of b's connection, and b being set to a null value, as an empty, unusable object.
  • Create a new connection when a copy is created. This depends on the sqlite API providing the necessary functionality. In particular, queries and other connection-specific data may have to be copied as well, which might be impractical
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文