3

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;

各変数がスコープ外になると、データベースポインタで2つのsqlite3_close呼び出しが発生します。リソースを別の変数に割り当てる必要がある場合、RAIIでこの問題をどのように克服しますか?

4

3 に答える 3

9

共有リソースの場合、参照カウントを使用するなど、それらへの参照が存在するかどうかを追跡する必要があります。1つの実装は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);
}
于 2010-07-18T01:22:43.323 に答える
3

接続をshared_ptrに入れます。割り当て時に行う必要があるのは、リソース(接続)の共有所有権を持つように「shared_ptr」を割り当てることだけです。それ以外の場合は、すでにブーストで実行され、C++0xに含まれているクラスの共有所有権を実装する必要があります。

于 2010-07-18T01:17:59.200 に答える
0

次の 4 つの基本的なオプションがあります。

  • おそらく を介して、参照カウントを使用しますshared_ptr。これは最も効率的ではありませんが、最も一般的な解決策です。
  • 割り当てを禁止します。ユーザーが SQLite オブジェクトをコピーできないようにします。代入演算子とコピー コンストラクターを非公開にします。その場合、ユーザーは代わりにポインターまたは参照を渡す必要があります。
  • 割り当てがリソースを「盗む」ようにします。これが何をするかauto_ptrです。の接続の所有権を取得し、空で使用できないオブジェクトとして null 値に設定されますa = babb
  • コピーの作成時に新しい接続を作成します。これは、必要な機能を提供する sqlite API に依存します。特に、クエリやその他の接続固有のデータもコピーする必要がある場合があり、これは実用的ではない可能性があります
于 2010-07-18T04:07:03.723 に答える