如果我们注释掉下面强调的行,我们会在控制台中获得777。 否则我们得到一些垃圾(-534532345)。 我的环境是Microsoft Visual Studio 2012 Pro。
class C
{
public:
C () { x = 777; }
void ou() {cout << x;}
protected:
int x;
};
class A
{
public:
A(C & rrc) : rc(rrc) {};
void koo () {rc.ou();}
protected:
C & rc;
};
int _tmain(int argc, _TCHAR* argv[])
{
C c;
C * pc = new C;
A a(*pc);
delete pc; // <<<< this line
a.koo();
return 0;
}
任何人都可以帮我弄清楚为什么我会看到这种行为吗?
答案 0 :(得分:7)
在您调用a.koo()时,您已删除其rc
引用所引用的基础对象。那当然是UB。接下来发生的事情可能是在给定平台上针对给定编译具有一致行为,甚至可能输出777(实际上,由于基础对象最近被删除,可能会输出777)。在您的情况下,似乎先前已分配给_tmain()的pc
对象的内存已被重新分配给已覆盖它的其他内容,或者您正在使用其内存分配器的调试版本显式地用一些固定值覆盖已删除/释放的内存,通常是非零而不是全部,但是可以识别的东西,如0xAAAAAAAA或0xDEADDEAD。由于-534532345是0xE023AF07(或0xFFFFFFFFE023AF07),我猜它是前者(内存已被分配给其他覆盖它的东西)。由于你的示例中对a.koo()的调用紧跟在delete pc
之后,我发现令人惊讶的是它已经很快被覆盖了,但技术上任何事都可能,因为它是UB。
答案 1 :(得分:4)
删除会留下您所遵循的悬空引用,从而导致未定义的行为。它不是C ++或MS VS中的漏洞。该语言允许许多非法操作未经检查,并让程序员不要调用UB。
答案 2 :(得分:4)
代码具有未定义的行为。您持有不再存在的对象的引用。因此,rc.ou()
行为未定义。
答案 3 :(得分:1)
如果你删除pc,那么A :: rc将指向垃圾位置和rc.ou();也将输出垃圾。这是预期的行为,无论您使用何种编译器,它都会执行此操作
Btw 99 [.99]%你认为你在编译器中发现了一个bug,这真的是你的错误