0

この小さなコードを考えると:

#include <iostream>
#include <assert.h>
using namespace std;


struct Foo
{
    // something
};


int main()
{

    Foo *p1 = new Foo;
    Foo * p2 = p1;
    assert(NULL != p1);
    delete p1;
    p1 = NULL;

    assert(NULL != p2);
    delete p2;

    cout << "everything is cool!" << endl;

    return 0;
}

を削除するp1と、2番目のassert(assert(NULL != p2);)が失敗しません。なぜですか?

出力 :everything is cool!

では、なぜのアサートがp2失敗しないのですか?

4

4 に答える 4

4

p1を削除すると、2番目のassert(assert(NULL!= p2);)が失敗しません。なぜですか?

削除p1または割り当てても、p2それ自体には影響しません。を削除p1した後も、p2そのアドレス、つまり無効なオブジェクトを指します。いわゆるダングリングポインタになります。もちろん、それにアクセスしたり削除したりすることは(あなたがしていることですが)未定義の振る舞いです。

于 2012-08-25T13:24:29.303 に答える
2
  1. 特に星を見てください。

    int i;
    
    int *p1 = &i;
    assert(p1 != NULL);
    
    int *p2 = p1;
    assert(p2 != NULL);
    
    *p1 = 10;
    assert(i == 10);
    assert(*p2 == 10);
    
    p1 = NULL; // does not affect the object p1 was pointing at
    
    assert(i == 10);
    assert(*p2 == 10);
    assert(p2 != NULL); // (which we already know, if the previous assert didn't crash)
    
  2. あなたはすべてがクールではないことを疑うのは正しいです。プログラムは、同じオブジェクトに対して削除演算子を2回呼び出します(「ダブルフリー」エラー)。これにより、ヒープが破損する傾向があります。プログラムを続行すると、ある時点で未定義の動作が見られます。未定義の振る舞いを持つことは、コンピュータプログラムを書くという点をむしろ打ち負かします。このようなエラーをすぐに明確に確認したい場合は、valgrindのmemcheckまたは同等のものの下で実行してください。

于 2012-08-25T13:52:13.097 に答える
1

C ++で最も大きく、初心者にとって最も紛らわしい誤称の1つは、「ポインタの削除」という用語です。deleteこれは間違いなく、式がその引数としてポインタをとるという事実に由来しています。

T * p = new T;  // #1
delete p;       // #2

ただし、実際に行われているのは、1行目で新しい動的な名前のないオブジェクトが作成されることです。これについてもう一度考えてみてください。1行目に作成されたオブジェクトを値とする変数はありません。実際、どのスコープにも存在しないため、オブジェクトは実際には手の届かないところにあります。私たちが持っているのはそれへのポインタだけです。

動的変数の有効期間を終了するには、delete式を使用する必要があります。ただし、オブジェクト自体ではなく、オブジェクトへのポインタしか実際に持つことができないことはすでにわかっているので、式は、削除するオブジェクトへのポインタを便利に受け入れます。

したがって、実際には、2行目で「式*pへのポインタを指定してオブジェクトを削除してdeleteいる」(つまり&*p == p)と言う必要があります。

deleteポインタ自体は、呼び出しの影響をまったく受けません。

*)はい、のような参照変数を使用することもできますT & r = *new T;が、それは非常識です。

于 2012-08-25T13:49:34.677 に答える
0

delete p;影響しませんppを指しているオブジェクトを破棄し、そのメモリを解放します。pまだ以前の価値があります。

于 2012-08-25T13:33:16.957 に答える