1

我有几个关于指针的问题。第一的:

 ObjectType *p; 
 p->writeSomething();

为什么可以在指针尚未初始化的情况下调用对象上的方法?如果我运行该代码,我会从控制台窗口中的“writeSomething()”获得输出。第二:

ObjectType *p;
if(p==NULL) 
cout<<"Null pointer";//This is printed out
p = new ObjectType;
delete p;
if(p==NULL)
   cout<<"Null pointer";
else
   cout<<"Pointer is not null";//This is printed out

为什么第二个 if 语句中的指针不是 null 以及如何检查指针是否未指向任何内存地址?我还想知道是否有任何方法可以检查程序执行完成时是否有一些内存没有被释放。例如,如果您忘记在代码中编写 1 个删除语句。

4

4 回答 4

7

第一个代码是未定义的行为,任何事情都可能发生,甚至看起来有效。它可能有效,因为调用是静态解析的,并且您没有访问该类的任何成员。

对于第二个片段delete没有将指针设置为NULL,它只是释放内存。指针现在悬空,因为它指向您不再拥有的内存。

于 2012-05-19T09:58:59.220 回答
3

您的代码当然表现出未定义的行为,但这里有一个示例说明为什么即使没有对象也可能调用成员函数:如果成员函数不引用类的任何成员对象,那么它将永远不需要访问您尚未初始化的内存的任何部分。这意味着,您的成员函数本质上是静态的。

如您所知,成员函数可以被视为具有隐式实例对象引用参数的普通自由函数。例如,Foo像这样定义的一个简单类,

struct Foo
{
    void bar() { std::cout << "Hello\n"; }
};

可以实现为一个单一的、自由的功能:

void __Foo_bar(Foo * this)
{
    std::cout << "Hello\n";
}

现在当你说Foo * p; p->bar();,这相当于一个免费的函数调用__Foo_bar(p);。您最终将无效指针传递给函数,但由于函数从不使用指针,因此不会造成任何伤害。

另一方面,如果你的类有一个成员对象,比如int Foo::n;,并且如果成员函数试图访问它,你的实现会尝试访问它this->n,这可能会导致一个直接的问题,因为你实际上是在取消引用一个无效的指针。

于 2012-05-19T10:30:50.057 回答
2
delete p;

释放内存,但不会更改存储在p.

标准 C++ 中没有检测指针是否引用无效内存的方法。不取消引用无效指针是您的责任。

您的第一个示例是未定义的行为。未定义行为的可能结果之一是程序按您预期的方式工作。同样,您有责任不编写具有未定义行为的程序。

在您的代码中,writeSomething()可能是一个非虚拟成员函数,它不会取消引用this,这就是为什么它恰好在您的编译器上为您工作。如果您尝试引用某些成员数据字段,很可能会遇到运行时错误。

于 2012-05-19T09:59:07.137 回答
0

delete将调用析构函数,ObjectType然后取消分配内存,但它没有明确地使您的指针NULL

作为良好的编程实践,这是您必须做的事情。

于 2012-05-19T10:03:12.727 回答