为什么C++会以这种方式运行?

Laz*_*zer 4 c++ arrays oop object

#include<stdio.h>

class A { public: int a;};

class B: public A {
    int c; 
    int d;
};

int main() {

    A* pA = new B[10];
    B* pB = new B[10];

    printf("\n%d", pA->a);
    pA++;
    printf("\n%d", pA->a);  // prints junk value

    printf("\n\n%d", pB->a);
    pB++;
    printf("\n%d", pB->a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

第二个printf打印垃圾值.

它应该指出它指向一个类型的对象B并通过它增加sizof(B).

为什么不会发生这种情况?

Ste*_*eel 19

不,不应该.声明的类型pAA*,所以它递增sizeof(A),这使它指向数组中第一个B的中间.


Jer*_*fin 11

它之所以脆弱,是因为你踩着它所做的一切来试图保证你的安全.除非你有足够的经验知道为什么会出现这些问题,以及如何避免这些问题,你应该:

  1. 忘了printf存在.请std::cout改用.
  2. 忘了new存在.请std::vector改用.

您可能还应该阅读C++常见问题解答,并密切关注那些说出某些内容的部分:"即使X是Y,X的数组也不是Y的数组."

编辑:至于为什么你看到你的行为,它很简单:指针算术是根据静态类型而不是动态类型定义的.这意味着它完全基于您为指针定义的指针类型,而不是它指向的内容.如果你说它指向一个A,但是然后指向一个B,那么算法仍然会像你所说的那样指向A.

  • @Alan:虽然`printf`确实没有引起这个特殊问题,但在C++中使用它仍然很少是一件好事.我不提倡任何东西来代替理解,但我确实主张遵循合理的规则,直到你理解得足以知道何时打破它们. (2认同)

Joh*_*itb 7

它只能在运行时知道.想象一下它有点变化

A* a;
if(runtimevalue)
  a = new A[10];
else
  a = new B[10];
Run Code Online (Sandbox Code Playgroud)

但那不会发生.C++强调速度,但这基本上使它成为一种确保操作安全的语言.Java,C#等已经解决了这个问题.

内核和设备驱动程序开发人员不希望有一个聪明的语言运行时.他们只是想让事情快速发展.

看看常见未定义的行为在C++中的问题为所有需要得到"固定"沿东西.它不再是C++了!