2

次の C++ コードを検討してください。

class test
{
public:
    int val;

    test():val(0){}
    ~test()
    {
        cout << "Destructor called\n";
    }
};

int main()
{
    test obj;
    test *ptr = &obj;
    delete ptr;

    cout << obj.val << endl;

    return 0;
}

動的に割り当てられたオブジェクトに対してのみ delete を呼び出す必要があることはわかっていますが、 obj はどうなるでしょうか?

さて、私はそのようなことをするべきではないことを理解しました。スマート ポインターの次の実装を書いている場合、そのようなことが起こらないようにするにはどうすればよいでしょうか。

class smart_ptr
{
public:
    int *ref;
    int *cnt;

    smart_ptr(int *ptr)
    {
        ref = ptr;
        cnt = new int(1);
    }

    smart_ptr& operator=(smart_ptr &smptr)
    {
        if(this != &smptr)
        {
            //  House keeping
            (*cnt)--;
            if(*cnt == 0)
            {
                delete ref;
                delete cnt;
                ref = 0;
                cnt = 0;
            }

            //  Now update    
            ref = smptr.ref;
            cnt = smptr.cnt;
            (*cnt)++;
        }
        return *this;
    }

    ~smart_ptr()
    {
        (*cnt)--;
        if(*cnt == 0)
        {
            delete ref;
            delete cnt;
            ref = 0;
            cnt = 0;
        }
    }
};
4

5 に答える 5

3

投稿で 2 つの異なる質問をしました。個別にお答えします。

しかし、今 obj はどうなるでしょうか?

プログラムの動作は未定義です。C++ 標準は、現在の状況についてコメントしていませんobj。実際、標準では、プログラムがエラーの前に何をするかについてもコメントしていません。単に定義されていません。

おそらく、コンパイラ ベンダーが何が起こるかを確約し、アセンブリを調べて何が起こるかを予測することはできますが、C++自体は何が起こるかを定義していません。

実際には1、標準ライブラリから警告メッセージが表示されるか、セグ フォールトが発生するか、またはその両方が発生する可能性があります。

1: Windows または MMU を備えた UNIX 系システムのいずれかで実行していると仮定します。他のコンパイラや OS には、他の規則が適用されます。


delete[ ing a stack variable] が発生しないようにするにはどうすればよいですか。

smart_ptrスタック変数のアドレスで初期化しないでください。そのための 1 つの方法は、 へのインターフェイスを文書化することsmart_ptrです。もう 1 つの方法は、ユーザーがポインタを に渡さないようにインターフェイスを再定義することsmart_ptrです。の呼び出しをsmart_ptr担当しnewます。

于 2012-11-20T16:56:52.693 に答える
1

Deleteはメモリ内のobjスペースにアクセスしようとしていますが、操作システムはこれを許可せず、(コアダンプされた)例外をスローします。

于 2012-11-20T17:00:30.633 に答える
1

new で割り当てられていないポインターで delete を使用したため、コードの動作は未定義です。これは、何かが起こる可能性があり、 に何が起こるかを言うのは不可能であることを意味しobjます。

ほとんどのプラットフォームでコードがクラッシュすると思います。

于 2012-11-20T16:57:00.103 に答える
0

他の回答で述べられているように、それは未定義の動作だけではありません。これはほぼ確実にクラッシュします。

最初の問題は、スタック変数を解放しようとすることです。

2番目の問題は、プログラムの終了時に、testデストラクタが呼び出されるときに発生しますobj

于 2012-11-20T17:01:56.167 に答える
0

どうなるかは未定なのでなんとも言えません。あなたができる最善のことは、特定の実装/コンパイラについて推測することです。

于 2012-11-20T16:56:48.590 に答える