デストラクタパターン
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 13/61。
mallocで作成されたすべてのオブジェクトは、最終的に解放する必要があります。allocationを処理するためにcreate_ functionを書いたのと同様に、cleanupを処理するためにfree_ functionを書きます。これがdestructor patternです。
重要なポイントは、解放はallocation の逆順で行わなければならないということです。constructor が最初に allocated internal members を allocation し、その後に構造体自体を allocation した場合、destructor は最初に構造体の members を free し、その後に構造体を free しなければなりません。
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // 安全チェック
free(p->name); // まず内部メンバーを解放
free(p); // 次に構造体自体を解放
}
開始時の NULL チェックにより、誰かが誤って無効なポインターを渡した場合でもクラッシュを防げます。internal の name 文字列を解放した後、構造体自体を解放します。先に p を解放すると、p->name へのアクセスを失い、メモリーリークを引き起こします。
destructor の使用は簡単です:
Person *alice = create_person("Alice", 30);
// ... alice を使用 ...
free_person(alice); // 完了したらクリーンアップ
このパターンにより、すべての memory が適切に解放されます。これがなければ、作成するすべてのオブジェクトが memory をリークし、最終的にプログラムの実行に必要な memory がなくなってしまいます。
チャレンジ
簡単Movie モジュールを作成して、オブジェクトの完全なライフサイクル、つまり作成と破棄の両方を示しましょう。割り当てられたすべてのメモリを正しい順序で適切にクリーンアップするデストラクタ関数の記述を練習します。
3つのファイルを作成します。
movie.h: 2つのメンバーを持つMovie構造体を Declare します。メンバーはchar *title(dynamically allocated な文字列)とint yearです。タイトルと年を受け取るコンストラクタcreate_movieと、Movie ポインターを受け取るデストラクタfree_movieの両方を Declare します。シンボルMOVIE_Hを使用して include ガードを設定します。movie.c: 両方の関数を Implement します。コンストラクタでは、構造体とその title 文字列のためにメモリを Allocate します(null 終端文字を忘れないでください)。デストラクタでは、メモリの Allocate と逆の順序で Free する必要があります。まず内部のtitle文字列を Free し、次に構造体自体を Free します。安全のため、デストラクタの先頭に NULL check を含めます。main.c: movie を Create し、その information を表示してから、メモリを適切に Clean します。
2つの入力を受け取ります。movie title(文字列)とrelease year(整数)です。
main ファイルでは、create_movie を使用して新しい movie を Create し、その information を表示してから、free_movie を呼び出してすべてのメモリを Free します。Free した後、確認メッセージを表示します。
次の format で出力します。
Movie: {title} ({year})
Memory freedたとえば、入力が Inception と 2010 の場合、出力は次のようになります。
Movie: Inception (2010)
Memory freed覚えておきましょう。適切なデストラクタの鍵は、逆の順序で Free することです。コンストラクタが first に Allocate したものは last に Free し、last に Allocate したものは first に Free します。
自分で試してみよう
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// 入力を読み取る
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: create_movieを使用して映画を作成する
// TODO: 次の形式で映画情報を出力する:
// Movie: {title} ({year})
// TODO: free_movieを使用して映画を解放する
// TODO: "Memory freed"を出力する
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ