这段C++代码是如何工作的?未初始化指针

4
可能是重复问题:
当我在空对象指针上调用成员函数时会发生什么?
class A {
  public:
    void foo() { cout << "Work";}
    void bar() { this->foo(); }//new edit, works too!
};

class B {
  private:
    A *a; //never initialized
  public:
    A& getA() {
      return *a;
    }
};

void SomeFunction() {
    B *b = new B();
    B& bRef = *b;
    bRef.getA().bar();//edited
    delete b;
}

我调用了SomeFunction(),但没有初始化变量"a",但它仍然可以正确打印出"Work"。我不明白为什么,应该会因为段错误而终止!


7
这就是未定义行为的美(读作:可怕之处)。 - AndersK
我把这个作为回答一个问题的答案发布了。接着发现它是错的!但是当我运行这个程序时,它打印出了正确的答案。感到困惑,我又发布了一个问题。 - Aniket Inge
3个回答

10

这是未定义的行为,但它可以在大多数编译器上工作。因为foo不是virtual并且它没有使用this指针。


使用了“this”,它仍然有效! - Aniket Inge
1
@PrototypeStark - 不,你不需要使用这个。不需要调用foo。因此也不需要调用bar。 - Henrik
@PrototypeStark 请看我的回答,了解为什么不使用 this - Kaz Dragon
@Henrik,我知道如果不需要调用“foo”,那么我就不需要调用“bar”。但是当我说“在内部使用‘this’指针调用‘foo’”时,我的意思很清楚。但是既然你说我没有使用“this”指针,我进行了更正并测试了一下。 - Aniket Inge

5

请记住,类只是C ++的构造。编译时,所有类方法都是接受隐藏的this参数的静态方法。

鉴于您的foo()方法从未引用任何数据成员,因此它永远不需要使用它,所以尽管this的值未初始化,它仍然可以正常运行。


教育性的。但是仍然有点可怕。 - Aniket Inge
1
在三个回答中,我选择了你的回答,因为你清楚地提到foo()仍然接受“this”指针。我的代码编辑证明它确实如此。不像Henrik的回答,他说“它之所以起作用是因为它不是虚拟的,并且它不使用这个指针”。 - Aniket Inge
-1 这个答案没有提到最重要的一点,即根据语言规范,这段代码的行为是未定义的,因此可能会因编译器而异。 - Chris Dickson

3
语义上来讲,
o.f(args)

是相同的意思

f(o, args)

所以你可以把你正在调用的函数 (A::foo()) 看作是等同于:
void A_foo(A* pthis)
{
    cout << "Work";
}

正如您所看到的,pthis从未被引用,因此不会发生无效的内存访问。即使您键入this->foo(),它也是完全相同的调用,this不需要被解引用。
至少,在编译器实现中,这是一种常见的方式。具体可能发生什么是未定义的,因此在Death Station 9000上运行代码可能会将小猫传送到太空中。请考虑小猫!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接