2

ポインターが NULL に設定されている場合、そのポインターへの参照も、それを介した参照も NULL になりません。実行しようとすると爆発するコンパイル可能な例を次に示します。

#include <string>
#include <iostream>

#define NULL 0

class Seedcoat {
public:
    //Seedcoat();
    std::string Name;
    int Weight;
};

class Seed {
public:
    //Seed();
    std::string Name;
    int Weight;
    Seedcoat* ItsSeedcoat;
};

class Apple {
public:
    //Apple();
    std::string Name;
    int Weight;
    Seed* ItsSeed;
};

int main()
{
///////Apple Objects Begin///////
    Apple       MyApple;
    Seed        MySeed;
    Seedcoat    MySeedCoat;

    MyApple.ItsSeed = &MySeed;
    MyApple.ItsSeed->ItsSeedcoat = &MySeedCoat;
    MyApple.ItsSeed->ItsSeedcoat->Weight = 2;

    if ( MyApple.ItsSeed != NULL) {
        std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n";
    }

    MyApple.ItsSeed = NULL;

    if ( MyApple.ItsSeed->ItsSeedcoat != NULL) {
        std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n";
    }

    return 0;
}

だから私の質問は:なぜこれは

MyApple.ItsSeed->ItsSeedcoat != NULL

true を返します。ItsSeed が NULL に設定されているため、そうではないと思いますが、ItsSeedcoat の重み値を参照しようとしますが、ItsSeed が存在しないため爆撃します。これを回避する簡単な方法があることに気づきました。この例は、私が観察している動作を示すためのものです。これは何か心配することはありますか?- または、これは正常な動作ですか? このようにした理由は何ですか?ありがとう。

4

7 に答える 7

3

C++ はそのような方法であなたの手を握ることはありません。ポインターを null に設定すると、そのポインターのみが null に設定されます。Java や Python で期待されるように、サブオブジェクトをクリアしたり、メモリを解放したりすることはありません。

ポインターを null に設定すると、アクセスすることはもはや合法ではないMyApple.ItsSeed->ItsSeedcoatため、何かが起こる可能性があります。

あなたの特定の問題では、構成がおそらくより良い解決策になると思います。ただし、C++ でメモリの割り当て/割り当て解除を管理する必要がある場合は、他の言語のガベージ コレクターとほぼ同等の機能を提供する適切なスマート ポインターを使用することを強くお勧めします。

また、一部のヘッダーでは既に C 用に定義されているため、自分自身を定義しないことNULLをお勧めします。C++03 では通常リテラルを使用することをお勧めしますが、C++11 ではキーワード0を使用できます。nullptr

于 2012-12-05T22:07:31.210 に答える
1

NULL に設定MyApple.ItsSeedした後は、ポインターを逆参照することはできません。これはMyApple.ItsSeed、式が許可されていないことを意味しますMyApple.ItsSeed->ItsSeedcoat

これは必ずしも例外をスローするわけではありませんが、その動作は未定義です。

于 2012-12-05T22:06:35.467 に答える
1

これは未定義の動作であり、何が起こる可能性があります。

特に、

MyApple.ItsSeed = NULL;
if ( MyApple.ItsSeed->ItsSeedcoat != NULL)

NULL ポインターを逆参照することはできません。それはそれと同じくらい簡単です。その場合、すべての動作が準拠しています。

于 2012-12-05T22:06:44.267 に答える
0

ポインターを null に設定すると、そのポインターへの参照もすべて null になります。ただし、コードにはポインターへの参照がありません。まったく異なる 2 つのポインタ オブジェクトがあり、一方に対して何を行っても他方には影響しません。(これは、私が知っているすべての言語に当てはまります。)

于 2012-12-05T22:47:31.673 に答える
0

C++ は、あなたが説明している種類の動作を実装していません。一部の言語では、オブジェクトはそのオブジェクトへのすべての「弱い」ポインターを追跡するため、そのオブジェクトが解放されると、それらのポインターはすべて自動的に NULL になります。ただし、C++ はそれらの言語の 1 つではありません。オブジェクトが解放されると、そのオブジェクトへの NO ポインターは自動的に NULL になります。オブジェクトへの特定のポインターが NULL になると、同じオブジェクトへの他のポインターが自動的に NULL になることはありません。そのような動作が必要な場合は、boost::weak_ptrまたはを参照してくださいstd::weak_ptr

于 2012-12-05T23:43:46.673 に答える
0

あなたの例では、Seed* である MyApple.ItsSeed を NULL に設定し、MyApple.ItsSeed->ItsS​​eedcoat を実行すると、NULL ポインターを逆参照しようとします。

于 2012-12-05T22:12:24.073 に答える
0

NULL ポインターを逆参照すると、未定義の動作が発生します。メンバーに到達するには、すでに NULL に設定されているItsSeedCoatpointer を逆参照する必要があります。ItsSeed

于 2012-12-05T22:07:11.627 に答える