对象(引用类型 - 堆)如何与存储在堆栈中的变量进行通信

时间:2010-03-09 09:50:04

标签: oop memory-management

因为我们知道引用类型总是存储在堆上,值类型在堆栈内存中。

e.g。

public Class A{
  public int myInt=10;
  public void Display(){
  }
}

这里,如果我创建了类A的对象,它会进入堆中,而myInt会进入堆栈中吗?

现在,类对象(堆)如何与myInt公共变量(堆栈)交互?

任何人都可以解释一下..

5 个答案:

答案 0 :(得分:4)

如果你在谈论.NET,我担心你的假设是错误的。值类型仅在不属于引用类型实例的一部分时才存储在堆栈中。即您的myInt作为A的任何实例的一部分存储在堆上。

答案 1 :(得分:1)

  

因为我们知道引用类型总是存储在堆

问问自己:引用类型的哪个部分存储在堆上?什么样的记忆?引用类型由什么组成?

- 主要由它的成员变量的内存组成。 1) 这些是存储在堆上的数据。因此,在您的示例中,这将是myInt变量。

如果它们是方法中的本地变量或它们的参数,则值类型 存储在堆栈中(如您所假设的)。这就是堆栈的用途:存储局部变量和参数(以及函数调用的返回指针)。


1)有时候还有一个所谓的vtable,它存储虚函数的地址。但这与这个问题无关。

答案 2 :(得分:0)

通常,定位变量是编译器的任务。

答案 3 :(得分:0)

如果您创建class A的实例,请说A obj=new A();在堆上创建类型为A的对象。堆上的此对象也构成了堆上的实例varialbe myInt以及其他成员变量(如果有的话)。并且您在堆上引用此对象,其中引用变量obj将位于堆栈上。例如,

class Mainclass{
main(){
A obj=new A();
//......all other code......
}
}

编辑:

.net开发者必须阅读:
Memory in .NetReference and values

答案 4 :(得分:0)

我会尽快与你交谈。 C#语言:

引用

  

因为我们知道引用类型总是存储在堆和值类型上   在堆栈记忆中。

TL; DR; 这不是真的。请阅读我在下面发布的详细信息。在您的情况下,类A的对象实例和myInt成员变量都将存储在堆上,而不管myInt是值类型的事实。

总结变量在堆和堆栈上的存储方式:

堆栈始终用于存储以下两件事:

  • 函数及其参数中引用类型局部变量的引用部分。
  • 值类型的局部变量和方法参数(结构,以及整合$ ers,bools,chars,DateTimes等)

以下数据存储在堆上:

  • 引用类型对象的内容。
  • 在引用类型对象中构造的任何内容。

E.g。

Main()
{
MyClass obj = new MyClass();
}

Class MyClass
{
   int32 i;
   Dataset dst;

   private void MyMethod(int32 j, dataset dst2)
   {
           int32 k;
           Dataset dst3;
   }

以下是内存分配详情:

  1. obj是一个对象引用 - Stack
  2. obj变量指向的Myclass实例 - Managed Heap
  3. 值类型成员变量i - 托管堆
  4. dst是一个数据集对象引用 - Managed Heap
  5. dst变量指向的数据集实例 - Managed Heap
  6. 值类型参数j - 堆栈
  7. dst2是一个数据集对象引用 - Stack
  8. dst2变量指向的数据集实例 - Managed Heap
  9. 值类型局部变量k - Stack
  10. dst3是一个数据集对象引用 - Stack
  11. dst3指向的数据集实例 - 托管堆
  12. 我想我已经涵盖了所有的排列和组合。

    再次引用

      

    现在,类对象(堆)如何与myInt公共变量交互   (叠层)?

    我想在这里添加的第一件事是对象和变量不会相互作用。它是代码(方法中存在的可执行IL指令),它与类实例(也称为对象)的公共变量进行交互。

    请参阅,CLR仅在内存中加载一次类型。因此,与您的Display方法相对应的所有IL指令都将集中在内存中,而不管您在程序中创建的类A的实例数。只有类A的实例(包含成员变量数据)才会在堆中占用不同的位置(精确的内存地址)。

    因此,每当执行Display方法的IL指令时,它都有一个指向this的指针,它是对堆中当前对象实例的引用。 this引用对于不同的对象实例是不同的。 this始终指向当前对象实例的起始内存地址布局。从那里开始,需要偏移量才能到达myInt所在的内存地址以访问/更改它。

    我希望这可以帮助你制作C#代码如何在CLR环境中运行的心理模型。