最近在看.NET中栈和堆的比较系列的技术文章,对于栈和堆的我还是个初学者
在学习过程中,有点疑问,请大虾们参考下~
首先下面是文章里的原话:
1. 引用类型总是放在堆中。(够简单的吧?) 
2. 值类型和指针总是放在它们被声明的地方。(这条稍微复杂点,需要知道栈是如何工作的,然后才能断定是在哪儿被声明的。)
 然后他举例说明
假如我们执行以下的方法: 
第一个例子
public int ReturnValue()
{
    int x = new int();
    x = 3;
    int y = new int();
    y = x;
    y = 4;
    return x;
}第二个例子
假如我们首先使用MyInt类 
public class MyInt
{
    public int MyValue;
}
接着执行以下的方法: 
public int ReturnValue2()
{
    MyInt x = new MyInt();
    x.MyValue = 3;
    MyInt y = new MyInt();
    y = x;
    y.MyValue = 4;
    return x.MyValue;
}以上的他讲的是很清楚,我也明白。但是有一个小小的疑问
public class MyInt
{
    public int MyValue;
}
这段代码按照开头那2句话和图解,MyInt是个类也就是引用类型,理所当然是放置在堆中的。
public int MyValue;这是个int型也就是值类型,根据上面第2句(值类型和指针总是放在它们被声明的地方)可以知道它也是放在堆中的,是吧。
所以上面第2张图我也能理解。好,既然是这样的话,我们看第一个例子的代码,他只不过是个方法而已。我认为要执行这个方法之前肯定要先有一个类是吧
既然这方法执行之前肯定有类包含的话,那不和第2个例子一样么?
就这点我不明白,如果按照文章里代码只给个方法理解那倒没什么问题。但是执行的时候不是这方法外肯定有类的么~那还不是都放在堆上了。
呵呵,也许我钻牛角尖了~
迷惑~~

解决方案 »

  1.   

    public class MyInt
    {
        public int MyValue;
    }
    那这个怎么说呢?  类里的变量,使用值类型,也是在栈?堆?  有点晕~
      

  2.   

    可以去MSDN上仔细瞧瞧理解一下
      

  3.   

    MSDN上貌似没有针对堆栈的讲解的吧 都是零散的 即使有术语繁多  有时翻译的还很奇怪...  不是很好理解的 
      

  4.   

    lz把类定义声明和成员变量定义的内容同定义具体对象搞混了
    注意,不要把声明和定义具体对象搞混乱了
    声明定义同存储无关,不要去套在一起
    和存储有关的只是形成对象的时候,也就是new的时候
    也就是说new的时候,new的是值类型,这个值类型就放在栈里
    如果new的是引用类型,那么放在栈里的就是指针,具体信息在堆里
    public int ReturnValue()
    {
        int x = new int(); //分配了具体对象x
        x = 3;
        int y = new int();
        y = x;
        y = 4;
        return x;
    }public class MyInt
    {
        public int MyValue; //写法和上面函数注释的x接近,但是这里不分配空间,不要想着存储的事情,这里只是定义声明
    }public int ReturnValue2()
    {
        MyInt x = new MyInt(); //这里开始才建立对象,分配存储,很明显引用类型,当然堆里
        x.MyValue = 3;
        MyInt y = new MyInt();
        y = x;
        y.MyValue = 4;
        return x.MyValue;
    }
    再次强调存储分配数据只和对象有关(只有对象占有存储,类声明是抽象概念不占有存储空间,这句话不要钻牛角尖,这是程序和程序员角度理解的,当然站在编译器角度都占有存储空间),和类这个抽象概念无关。到底在堆里还是在栈里,要看分配存储空间的时候看也就是形成对象(new)的时候,和声明定义的时候无关。
      

  5.   

    再次强调存储分配数据只和对象有关(只有对象占有存储,类声明是抽象概念不占有存储空间,这句话不要钻牛角尖,这是程序和程序员角度理解的,当然站在编译器角度都占有存储空间),和类这个抽象概念无关。到底在堆里还是在栈里,要在分配存储空间的时候也就是形成对象(new)的时候来观察,在声明定义的时候不要关心存储位置。
      

  6.   

    -----------------------------
    MyValue是类的成员,声明对象的时候需要分配内存,这个内存是属于该对象的,所以在堆中。
    类的成员方法中的局部变量不是类的成员,在声明对象的时候不会分配内存,只有在调用该方法时才会被分配内存,该内存是跟对象无关的,所以在栈中。
    所以首先区分类成员和方法中局部变量的区别。不知道我这样说好不好理解
      

  7.   

    MyValue是类的成员,声明对象的时候需要分配内存,这个内存是属于该对象的,所以在堆中。
    这句和上面14楼gogogo兄弟的貌似有冲突撒
    lz把类定义声明和成员变量定义的内容同定义具体对象搞混了 
    注意,不要把声明和定义具体对象搞混乱了 
    声明定义同存储无关,不要去套在一起 
    和存储有关的只是形成对象的时候,也就是new的时候 
    也就是说new的时候,new的是值类型,这个值类型就放在栈里 
    如果new的是引用类型,那么放在栈里的就是指针,具体信息在堆里 是我理解错了? 到底声明类的对象的时候要分配内存,而且已经在堆中?
      

  8.   

    前边可能罗嗦了,其实就是一句话,存储在什么地方不要任何代码都去看这个问题,只在分配对象的时候也就是new的时候才来观察存储的问题就一切都可以理解了。
      

  9.   

    ------------------------
    定义类和声明对象是两个东西
    类的定义就是你的原代码,是一个模板,除了它的静态成员外它不会被分配其它内存
    对象是类的一个实例,它是根据类这个抽象模板实例化出来的一个具体,C#中,通过new 关键字通知系统声明一个该类型的对象
    所以我说的跟gogogo说的不矛盾
      

  10.   

    举个例子说public class Program
    {
        static void main()
        {
            A a;           // 此处声明了一个类a的引用变量,它其实是一个指针而不是对象,注意,此时它指向Null,
            a = new A();   // 此处声明了一个类A的对象,clr会给它分配内存,并将它的句柄传给引用变量a,a此时指向这个新声明的对象
             (new A()).a = 10;  // 声明了一个对象,但是没有任何引用变量持有它的句柄,这个对象在内存中会一直存活到下一次垃圾收集
             A b = a;       // 此时b引用变量握有a指向对象的相同句柄
        }
    }
    public class A
    {
        public int a;
    }