2012年10月5日金曜日

言語C でスコープドポインタを実現する(その2)

新しい参照の作成

ローカル変数として参照を作成するときはつぎのようにする。
 lwd_Reference r = new_lwd_Reference(new_C("3345g"),
  (void (*)(void* object))C_finalize);
参照を生成するとき、第1引数としてオブジェクトのポインタを、第2引数にそのオブジェクトのデストラクタを指定する。

構造体やクラスのメンバが参照の場合も同様に初期化できる。

関数から復帰時に自動的に解放されるオブジェクト

スコープドポインタとしての動作を確認する例を示す。
テストに使用する簡単なクラス Cはつぎのようなもの。
/****************************************************************
 test target C
****************************************************************/

static boolean cFinalized;

typedef struct C* C;
struct C {
 char* string;
};

C new_C(char* string) {
 C this = (C)malloc(sizeof(struct C));
 if (this != null) {
  cFinalized = false;
  this->string = strdup(string);
 }
 printf("C object created.\n");fflush(stdout);
 return this;
}

void C_finalize(C this) {
 if (this != null) {
  printf("C object finalized. %s\n", this->string);fflush(stdout);
  if (this->string != null)
   free(this->string);
  free(this);
  cFinalized = true;
 }
}
コンストラクタとデストラクタがあるだけだが、デストラクタが実行されると外部変数の cFinalizedを trueにセットする。

テストケースはつぎの通り。
static void function0() {
 reference r = new_reference(new_C("3345g"),
  (void (*)(void* object))C_finalize);

 Assert_false("まだ削除されていないはず。", cFinalized);
}

void testAutoCollect(TestCase testCase) {
 Assert_false("まだ削除されていないはず。", cFinalized);
 function0();
 Assert_true("削除されているはず。", cFinalized);
}
testAutoCollect関数から呼ばれた function0関数の中で、参照 rを生成する。
関数復帰直前に cFinalizeは未だ falseであるが、testAutoCollect関数に戻ってきた後は cFinalizedが trueになる。

実行すると、標準出力にはつぎが出力されている。
[CUnit] ./ReferenceTest: testAutoCollect
C object created.
C object finalized. 3345g
デストラクタを明示的に呼んではいないが、トレースログにはデストラクタが呼ばれている様子がわかる。

2万円以上のカードをパスケースに入れて改札機にタッチしますと他のカードが処理されることがあります。 -- それは不思議な現象だ

0 件のコメント:

コメントを投稿