【问题标题】:C++ scope on heap堆上的 C++ 范围
【发布时间】:2019-05-30 18:53:03
【问题描述】:

为什么我在删除它的范围后得到输出为 10?我创建了一个类A,它有一个指针类型的成员变量和另一个类B,它有另一个成员变量x。现在我在堆上为 B 分配内存,为 x 分配值为 10。为了创建 A 类的实例,我使用了 x 的内存地址。现在我正在删除对象 b 并打印类 A 的指针 ref 的值。 我明白为什么我得到输出为 10,因为我们可以看到持有该值的内存不再保留在堆上?

#include<iostream>
using namespace std;

class A
{    
   public:
   int *ref;
   A(int *ref):ref(ref)
   {
   }
};

class B{
   public:
   int x;
   B(int x):x(x){}
};

int main()
{
   B *b=new B(10);
   A a(&b->x);
   delete b;
   cout<<*a.ref<<endl; 
}

【问题讨论】:

  • 几乎所有PC中的删除操作都不会擦除资源,而只是释放它们占用的空间以供将来使用。所以数据可能仍然存在一段时间,但访问该数据的结果是不确定的。
  • 离题,但您以错误的方式使用了术语范围。范围是指名称可见的源代码部分。它不是指变量的生命周期,通常称为范围。因此,在堆上分配的数据具有无限的范围(因为它会一直存在,直到您将其删除),但指向该数据的任何指针变量都具有正常的范围规则。

标签: c++ scope heap-memory


【解决方案1】:

这是因为悬空指针效应。虽然我们已经删除了内存数据还没有被擦除或者没有其他数据存储在那里并且我们的指针仍然指向那个内存。

供参考 https://www.geeksforgeeks.org/dangling-void-null-wild-pointers/

【讨论】:

    【解决方案2】:

    这是未定义的行为。例如,当我在 MSVC 中运行您的示例时,我的输出是 -572662307

    如果您尝试访问无效内存,我们无法保证会发生什么。可能会发生的情况是它无论如何都会访问无效内存,如果该内存没有改变,您可能会得到旧值。这实际上是一件坏事,因为该程序似乎按预期运行,而实际上并非如此。

    我明白为什么输出为 10,因为我们可以看到该内存 持有该值不再保留在堆上?

    内存不再有效,但数字10 可能仍在该内存中,而a.ref 仍指向该内存。所以即使内存无效,10 可能仍然存在。

    【讨论】:

      【解决方案3】:

      您所拥有的是未定义的行为,因为程序正在访问不再属于它的内存。
      delete 释放内存以便可以重用,但这并不意味着该内存位置中的值设置为零(如果这是您所期望的)。

      【讨论】:

        猜你喜欢
        • 2012-03-04
        • 2020-10-09
        • 2014-06-08
        • 2018-02-23
        • 1970-01-01
        • 2014-08-12
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        相关资源
        最近更新 更多