BIU*_*BIU 2 c++ visual-studio-2010
我有一个问题,为什么我可以访问某些内存,我认为这与我理解(或不理解)编译器如何在内存中保存内容的方式有关.这是我正在使用的示例代码:
头文件:
#include <iostream>
using namespace std;
class A
{
public:
int value;
A (int newValue = 5)
{
value = newValue;
cout << "A()" << endl;
}
~A() { cout <<"~A()" << endl; }
void func1() {cout << "A::func1()" << endl; }
};
class B : public A
{
public:
B() { A::value = 0; cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
virtual void func1 () { cout << "B::func1()" << endl; }
};
class C : public B
{
public:
C() { cout << "C()" << endl; }
~C() { cout << "~C()" << endl; }
virtual void func1() { cout << "C::func1()" << endl; }
};
Run Code Online (Sandbox Code Playgroud)
.cpp文件:
int main()
{
int i;
cout << endl;
A* pA = new A (5);
B* pB = new B;
C* pC = new C;
pA->func1();
pB->func1();
pC->func1();
delete pA;
delete pB;
delete pC;
cout << endl;
//here is my first question - why don't I get a compiler error here?
//why does the compiler know what this is? Didn't I delete it?
A* ppA = pC;
//here is my second question - why does this work?
//didn't I clear this memory?
ppA->func1();
B bObject;
B* ppB = &bObject;
ppB->func1();
cin >> i;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题就在评论中 - 为什么我没有在这些方面出错?
如果我改变.h文件,从而func1()为virtual在A为好,我得到一个访问冲突上线,但仍然没有编译时错误.
谢谢你的任何解释:)
编译器不会跟踪指针是否指向合法对象.这是一个复杂的分析,在大多数常见情况下都是不可能的.这就是为什么在将删除的指针指定给另一个指针时不会生成错误的原因.
删除对象不会自动清除对象占用的内存.它将在未来的某个不确定点被覆盖,所以你永远不要依赖它.这称为未定义的行为,未定义行为的标志之一是,即使不应该这样做,它似乎也可以工作.
第一个问题的答案很简单:指令是在编译时编写的.编译器显然不知道该值是否已被删除,因此它只是盲目地复制了pCover 的值ppA.
你的第二个问题的答案是:它可能不起作用.你进入了可怕的未定义行为之地.想想爱丽丝梦游仙境,没有猫指导你.
基本上当你调用operator delete指针时,你告诉操作系统它可以在需要时覆盖内存."如果需要的话.没有实际的内存擦除,只是承诺你将不再使用那块内存.
因此,当您尝试访问要调用的虚拟表时func1,数据可能仍然存在.或不.在这种情况下你会崩溃(如果你很幸运).但是你应得的,你违背了对操作系统的承诺,所以现在一切都有了.
编辑:注意,func1从来没有实际使用过this,所以如果它不是虚拟的你可以说((A*)0)->func1(),它会工作得很好.