-4

如果我们注释掉下面强调的行,我们会在控制台中得到 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;
}

谁能帮我弄清楚为什么我会看到这种行为?

4

4 回答 4

7

在您调用 a.koo() 时,您已删除其rc引用所指的基础对象。那当然是UB。接下来发生的事情很可能在给定平台上针对给定编译具有一致的行为,甚至可能输出 777(实际上,可能会输出 777,因为最近删除了底层对象)。在您的情况下,似乎先前分配给 _tmain() 的内存pc对象已被重新分配给其他已覆盖它的东西,或者您正在使用调试版本,其内存分配器用某个固定值显式覆盖已删除/已释放的内存,通常非零且不是全部,但其他可识别的东西,如 0xAAAAAAA 或0x死亡。由于 -534532345 是 0xE023AF07(或 0xFFFFFFFFE023AF07),我猜它是前者(内存已分配给其他已覆盖它的东西)。由于在您的示例中对 a.koo() 的调用紧随其后delete pc,我发现它这么快就被覆盖了,但从技术上讲,因为它是 UB,所以一切皆有可能。

于 2013-02-27T23:08:18.067 回答
4

删除会给您留下一个悬空的引用,您会跟随它,导致未定义的行为。它不是 C++ 或 MS VS 中的漏洞。该语言允许许多非法操作不受检查,并让程序员不要调用 UB。

于 2013-02-27T23:08:28.900 回答
4

该代码具有未定义的行为。您持有一个不再存在的对象的引用。所以,rc.ou()行为是不确定的。

于 2013-02-27T23:08:30.100 回答
1

如果你删除 pc,那么 A::rc 将指向垃圾位置和 rc.ou(); 也会输出垃圾。这是预期的行为,无论您使用什么编译器,它都会这样做

顺便说一句,99[.99]% 的时间你认为你在编译器中发现了一个错误,这真的是你的错误

于 2013-02-27T23:08:54.030 回答