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

返回真。我认为它不会因为 ItsSeed 设置为 NULL - 但它仍然尝试引用 ItsSeedcoat 的权重值 - 然后我认为它会爆炸,因为 ItsSeed 不存在。我意识到有一些简单的方法可以解决这个问题——这个例子只是为了展示我正在观察的行为。这有什么好担心的吗?- 或者这是正常行为?这样做的原因是什么?谢谢。

4

7 回答 7

3

C++ 不会以这种方式握住你的手。将指针设置为 null 只会将该指针设置为 null。它不会像您在 Java 或 Python 中所期望的那样清除任何子对象或释放任何内存。

一旦将指针设置为 null,访问就不再合法,MyApple.ItsSeed->ItsSeedcoat因此任何事情都可能发生。

在您的特定问题中,我认为组合可能是一个更好的解决方案。但是,如果您确实需要在 C++ 中管理内存分配/释放,我强烈建议您使用适当的智能指针,它为您提供的功能与其他语言中的垃圾收集器大致相等。

我还建议不要定义NULL自己,因为某些标头已经为 C 定义了它。在 C++03 中,我通常建议使用文字0,而在 C++11 中,您可以使用nullptr关键字。

于 2012-12-05T22:07:31.210 回答
1

设置MyApple.ItsSeed为 NULL 后,不允许取消引用指针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 指针会导致未定义的行为。为了访问成员,您必须取消引用已设置为 NULLItsSeedCoat的指针。ItsSeed

于 2012-12-05T22:07:11.627 回答
0

在您的示例中,您将作为 Seed* 的 MyApple.ItsSeed 设置为 NULL,然后当您执行 MyApple.ItsSeed->ItsS​​eedcoat 时,您尝试取消引用 NULL 指针。

于 2012-12-05T22:12:24.073 回答
0

After setting a pointer to null, any references to that pointer are also null. In your code, however, you don't have references to the pointer; you have two, totally distinct pointer objects, and what you do to one has no effect on the other. (This is true in every language I know.)

于 2012-12-05T22:47:31.673 回答
0

C++ does not implement the kind of behavior that you are describing. In some languages, an object keeps track of all "weak" pointers to it so that when that object is freed, all of those pointers gets NULL'ed automatically. C++ is not one of those language, however. When an object is freed, NO pointers to that object get NULL'ed automatically. When a particular pointer to an object gets NULL'ed, NO other pointers to the same object get NULL'ed automatically. If you need that kind of behavior, look at boost::weak_ptr or std::weak_ptr.

于 2012-12-05T23:43:46.673 回答