SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

GDBMであそんでみたよ

薄いwrapperから連想配列まで

  • X ポスト
  • このエントリーをはてなブックマークに追加

メモリ管理を楽にする

 極薄wrapper版、datumの扱いはハダカのままなのでdptrをfree()するのが面倒だし、忘れやしないかとヒヤヒヤですね。使い終わったら勝手にfreeされるよう仕向けましょう。datumから導出し、デストラクタでfree()するauto_datumを用意します。auto_ptr/unique_ptrと同様のカラクリです。

list-05
// gdbm_db.h(部分)
namespace gdbm {
  ...
  struct auto_datum : datum {
    auto_datum();
    auto_datum(datum& d);
    auto_datum(auto_datum& d);
   ~auto_datum();
    auto_datum& operator=(datum& d);
    auto_datum& operator=(auto_datum& d);
  private:
    void free();
  };

  bool empty(const datum& d);
}
list-06
// gdbm_db.cpp(部分)
...
namespace gdbm {

  auto_datum::auto_datum() {
    dptr = 0;
    dsize = 0;
  }

  auto_datum::auto_datum(datum& d) {
    dptr = d.dptr;
    dsize = d.dsize;
  }

  auto_datum::auto_datum(auto_datum& d) {
    dptr = d.dptr;
    d.dptr = nullptr;
    dsize = d.dsize;
    d.dsize = 0;
  }

  auto_datum::~auto_datum() {
    free();
  }

  auto_datum& auto_datum::operator=(datum& d) { 
    if ( this != &d ) {
      free();
      dptr = d.dptr;
      dsize = d.dsize;
    }
    return *this;
  }

  auto_datum& auto_datum::operator=(auto_datum& d) { 
    if ( this != &d ) {
      free();
      dptr = d.dptr;
      d.dptr = nullptr;
      dsize = d.dsize;
      d.dsize = 0;
    }
    return *this;
  }

  void auto_datum::free() {
    ::free(dptr);
    dptr = nullptr;
  }

  bool empty(const datum& d) {
    return d.dptr == nullptr;
  }

}

 コピー・コンストラクタやコピー・オペレータの扱いが少々ややこしくなっています。fetch/firstkey/secondkey()の戻り値であるdatumをauto_datumで引き取れば、メモリの解放はauto_datum(のデストラクタ)におまかせです。

list-07
void store() {
  gdbm::db dbx("trial.db", 512, GDBM_NEWDB);
  assert( dbx.is_open() );

  array<const char*,4> keys     = { "apple",  "orange", "grape",  "apple" };
  array<const char*,4> contents = { "まっく", "みかん", "ぶどう", "りんご" };

  datum key;
  datum content;

  for ( size_t i = 0; i < keys.size(); ++i ) {
    key.dptr = const_cast<char*>(keys[i]);
    key.dsize = strlen(keys[i]) + 1;
    content.dptr = const_cast<char*>(contents[i]);
    content.dsize = strlen(contents[i]) + 1;
    int result = dbx.store(key, content);
    assert( result == 0 );
  }
  cout << "3 entries stored." << endl;
}

void fetch() {
  gdbm::db dbx("trial.db", 512, GDBM_WRCREAT);
  assert( dbx.is_open() );

  array<const char*,4> keys     = { "apple",  "orange", "grape",  "peach" };

  for ( const char* target : keys ) {
    datum key;
    key.dptr = const_cast<char*>(target);
    key.dsize = strlen(target) + 1;
    gdbm::auto_datum content =dbx.fetch(key);
    if ( empty(content) ) {
      cout << target << " not found..." << endl;
    } else {
      cout << target << " = " << content.dptr << endl;
    }  
  }
  cout << "--- list all entries ---" << endl;
  gdbm::auto_datum key = dbx.firstkey();
  while ( !empty(key) ) {
    gdbm::auto_datum content = dbx.fetch(key);
    cout << key.dptr << " = " << content.dptr << endl;
    key = dbx.nextkey(key);
  }
}

次のページ
std::stringインターフェース

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7216 2013/06/26 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング