2013年10月6日日曜日

C++ delete演算子

前回の続き2
動的に確保したメモリは解放しなければなりません。
newで確保したメモリはdelete演算子を使って解放します。対象がオブジェクトの場合は
delete演算子を使うことで、メモリを解放する直前にデストラクタが呼ばれます。

PeachBox *pPeachBox = new PeachBox;
        :
delete pPeachBox;       //削除するオブジェクトへのポインタ


オブジェクトを動的なメモリ確保と解放するサンプルプログラム
#include <iostream>

using namespace std;

class PeachBox{
public:
    PeachBox(){
        cout << "Created PeachBox's Object!!!" << endl;
    }
    ~PeachBox(){
        cout << "Deleted PeachBox's Object!!!" << endl;
    }
};

int main(void)
{
    //オブジェクトを生成
    PeachBox *pPeachBox = new(std::nothrow) PeachBox;

    //NULLでないことを真面目に判定   
    if (pPeachBox != NULL) {
        delete pPeachBox;      //オブジェクトを削除
        pPeachBox = NULL;    //未使用になった時点でNULLを代入しておく
    }

    return 0;
}

実行結果
# ./test
Created PeachBox's Object!!!
Deleted PeachBox's Object!!!

いつもながらに、たいしておもしろくないプログラムではありますが...(^_^;)
ここで、突然newのあとに(std::nothrow)という見慣れない記述が出てきています。

これはメモリが確保できなかったときに、例外を投げない代わりにヌルポインタを
返すようにするものです。

通常メモリ確保失敗の例外が発生すると、std::bad_allocでプログラムが突然
終了してしまいます。

実際のシステムでは動的なメモリ確保している箇所も多く、例外が発生すると
どこで異常終了したか、調べるのが困難になります。 
例外ハンドラまで作り込まれているケースはまれでしょうし。
また、異常時に期待する終了処理が正しく行われないことで、重要なデータが
消失することもあるかもしれません。

少なくともどこのメモリ確保で異常終了したかをトレースできるよう、異常系の
作り込みのためにも、newのあとの(std::nothrow)を強く推奨いたします。(^^)

あと最後のほうの pPeachBox = NULL; の部分ですが、こちらも重要です。

かなり長いプログラムなどになってくると、間違って使用するとか2重解放するとかを
やってしまいがちです。(実話)
これらのうっかりミスを防ぐために未使用ポインタへのNULL代入も強く推奨いたします。(^^)

今日の名言
悲しみと苦痛は、やがて「人のために尽くす心」という美しい花を咲かせる土壌だと
考えましょう。心をやさしく持ち、耐え抜くことを学びましょう。強い心で生きるために
言い換えれば、あせらずに、苦情を言わずに生きるために-できる限りの努力をすれば
いつかは楽しい満ち足りた生活を送れる日がやってきます。
                                    ヘレン・ケラー

苦難は真理に向かう第一歩である。戦争であれ、嵐であれ、女の怒りであれ、苦難を
見事に耐え抜いたものは、たとえ18歳であろうと80歳になっていようと、非常に
貴重な体験をした事になる。
                                    バイロン卿

分別と忍耐力に支えられた炎のごとき情熱を持つ人は、一番成功者になれる資格がある
                                    デール・カーネギー