zoukankan      html  css  js  c++  java
  • C#【堆与栈 值类型 引用类型】

    先说C#中值类型和引用类型

    概念:

    1.值类型:数据存储在内存的堆栈中,从堆栈中可以快速地访问这些数据,因此,值类型表示实际的数据。

    2.引用类型:表示指向存储在内存堆中的数据的指针或引用(包括类、接口、数组和字符串)。

    C#中定义的值类型包括原类型(Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal)、枚举(enum)、结构(struct)

    引用类型包括:类、数组、接口、委托、字符串等。

    我们要非常的清楚堆和栈是两个不同的概念 ,在C#中,我们把引用类型放在堆中,把值类型放在栈中。

    ,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。

    ,就是那些由 new 分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个 new 就要对应一个 delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。堆可以动态地扩展和收缩。

    堆和堆栈区别:

    堆和堆栈是两个不同的概念,在内存中的存储位置也不相同,

    堆一般用于存储可变长度的数据,如字符串类型;

    堆栈则用于存储固定长度的数据,如整型类型的数据int。由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。在进行数据操作时,对于值类型,由于每个变量都有自己的值,因此对一个变量的操作不会影响到其它变量;对于引用类型的变量,对一个变量的数据进行操作就是对这个变量在堆中的数据进行操作,如果两个引用类型的变量引用同一个对象,实际含义就是它们在堆栈中保存的堆的地址相同,因此对一个变量的操作就会影响到引用同一个对象的另一个变量。

    如图如果我们定义一个数组

    并且赋值 int[] nums={1,2,3};

    nums当中保存 的是堆中的地址:例如:0x001

    nums[0]:访问的是堆中的内容

    那么请接着看如下代码:

    public void Method1(){
    // Line 1
    int i=4;
    // Line 2
    int y=2;
    //Line 3
    class1 cls1 = new class1();
    }
    

    (参照图片理解)

    第1行:当这行代码执行时,编译器为它分配一小块栈内存。运行时栈负责提供程序所需的内存;

    第2行:程序继续执行。如同名字一样,栈在第一块内存的顶部分配了一块内存。

    第3行:在第3行,我们创建了一个对象。当该行执行时,真实的对象存储在另一种叫“堆”的内存中。堆用于动态分配内存。

     

    值传递引用传递:

    引用类型作为参数时:

    1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值
    2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值
    3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值

    值传递:传的是对象的值。
    引用传递:传的是栈中对象的地址。

    现在用例子来说明传值跟传地址的不同:

    class T
        {
            public void Display()
            {
                StringBuilder strb1 = new StringBuilder();
                StringBuilder strb2 = new StringBuilder();
                Test1(strb1);
                Test2(ref strb2);
                string str1 = strb1.ToString(); //str1值:"A"
                string str2 = strb2.ToString(); //str2值:"BC"
            }
           public void Test1(StringBuilder strb)
            {
                //strb和strb1是两个栈中对象,但指向相同的地址,这个操作是改变堆中对象
                strb.Append("A");
    
                //这里将strb指向一个新的堆中对象,所以后面的操作与strb1指向的栈中对象无关
                strb = new StringBuilder("B");
                strb.Append("C");
            }
    
           public void Test2(ref StringBuilder strb)
            {
                //这里的strb和strb2是同一个栈中对象,所以改变strb的值使其指向另一个对象也等于改变strb2
                strb = new StringBuilder("B");
                strb.Append("C");
            }
        }
    

      

     

  • 相关阅读:
    C语言程序设计I—第四周教学
    C语言程序设计I—第三周教学
    C语言程序设计I—第一周教学
    软工实践(四)——热词统计
    软工实践(三)——结对第一次作业(原型设计)
    软工实践(二)——构建之法读后感
    软工实践(一)——目标和规划
    庄子修身养性哲学
    $Matrix-Tree$定理-题目
    $Matrix-Tree$定理-理论
  • 原文地址:https://www.cnblogs.com/wjk921/p/4771602.html
Copyright © 2011-2022 走看看