当它的对象超出范围时,为什么该指针有效? (以及其他一些奇怪的行为)

时间:2017-07-28 09:47:09

标签: c++ pointers scope

我还是c ++的新手并且一直在研究对象范围 我测试了下面的代码并目睹了一些奇怪的行为。

struct Test
{
    int value, value2;
    Test() : value(1), value2(10) {};
};


Test* GetTestPointer() {
    Test t;
    t.value = 20;
    return &t;
}

int main() {
    Test* tp = GetTestPointer();
    int a = tp->value;
    int b = tp->value2;
    cout << a << endl;
    cout << b << endl;

    return 0;
}

输出:

20
10

我认为Test t会超出范围,因此在main中取消引用其值会抛出异常或空值。为什么它会像对象还活着一样获得有效值?

实际上这就是我最初的尝试:

Test* tp = GetTestPointer();
cout << tp->value << endl;
cout << tp->value2 << endl;

输出:

20
18223279

此处value2的行为无效,但我可以value就好了。
相反,我尝试重新排序:

Test* tp = GetTestPointer();
cout << tp->value2 << endl;
cout << tp->value << endl;

输出:

10
1459403656

请注意,当我按预期正确启动tp new时,没有发生这种情况。

我知道在现实生活中我永远不会写这样的代码,但我真的很好奇为什么会发生这种情况。

  1. 在这种情况下t何时超出范围?
  2. cout的排序与tp取消引用的内容有什么关系?
  3. 为什么当我将它们保存在缓冲区中时,我能获得正确的值吗?

1 个答案:

答案 0 :(得分:2)

你很幸运能够获得正确的价值,但一般情况下它是未定义的行为,你的编译器应警告你。

尝试将您的示例扩展为以下内容:

new

您将看到不同的输出,因为您的本地范围delete对象被另一个函数调用覆盖。

当您使用{{1}}语句时,您的对象不是在本地创建的,而是在HEAP内存上创建,因此当您退出函数范围时它是有效的。在这种情况下,您必须使用{{1}},以便稍后删除此对象。