C#中的值类型和引用类型

本文介绍了C#中的值类型(如简单类型、结构类型、枚举类型)和引用类型(如类、接口、数组)的区别。值类型存储在栈中,而引用类型在堆中分配。在参数传递时,值类型会复制一份副本,而引用类型传递的是对象引用。文章还讨论了字符串string的特殊性,虽然它是引用类型,但在参数传递时表现得像值类型。此外,还提到了装箱和拆箱的概念,以及C#中堆和栈的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        一、值类型和引用类型变量的存储

    首先,变量是存储信息的基本单元,而对于计算机内部来说,变量就相当于一块内存空间。
    C#中的变量可以划分为值类型和引用类型两种:
    值类型:简单类型、结构类型、枚举类型
    引用类型:类、代表、数组、接口。

    (一)值类型和引用类型内存分配

    值类型是在栈中操作,而引用类型则在堆中分配存储单元。栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的内存空间,可以根据程序的运行情况动态地分配内存的大小。因此,值类型总是在内存中占用一个预定义的字节数(比如,int占用4个字节,即32位)。当声明一个值类型变量时,会在栈中自动分配此变量类型占用的内存空间,并存储这个变量所包含的值。.NET会自动维护一个栈指针,它包含栈中下一个可用内存空间的地址。栈是先入后出的,栈中最上面的变量总是比下面的变量先离开作用域。当一个变量离开作用域时,栈指针向下移动被释放变量所占用的字节数,仍指向下一个可用地址。注意,值类型的变量在使用时必须初始化.

    而引用类型的变量则在栈中分配一个内存空间,这个内存空间包含的是对另一个内存位置的引用,这个位置是托管堆中的一个地址,即存放此变量实际值的地方。.NET也自动维护一个堆指针,它包含堆中下一个可用内存空间的地址,但堆不是先入后出的,堆中的对象不人在程序的一个预定义点离开作用域,为了在不使用堆中分存的内存时将它释放,.NET将定期执行垃圾收集。垃圾收集器递归地检查应用程序中所有的对象引用,当发现引用不再有效的对象使用的内存无法从程序中访问时,该内存就可以回收(除了fixed关键字固定在内存中的对象外)。(垃圾收集器原理?

    但值类型在栈上分配内存,而引用类型在托管堆上分配内存,却只是一种笼统的说法。更详细准确地描述是:

    1、对于值类型的实例,如果做为方法中的局部变量,则被创建在线程栈上;如果该实例做为类型的成员,则作为类型成员的一部分,连同其他类型字段存放在托管堆上,

    2、引用类型的实例创建在托管堆上,如果其字节小于85000byte,则直接创建在托管堆上,否则创建在LOH(Large Objet Heal)上。

    比如一下代码段:

        
public class Test
    {
        private int i;    //作为Test实例的一部分,与Test的实例一起被创建在GC堆上
        public Test()
        {
            int j = 0;     //作为局部实量,j的实例被创建在执行这段代码的线程栈上
        }
    }

    当执行语句:Test T = new T(); T.j=0;时,其内存分配过程如下:

        

    (二)嵌套结构的内存分配 

    所谓嵌套结构,就是引用类型中嵌套有值类型,或值类型中嵌套有引用类型。

    引用类型嵌套值类型是最常见的,上面的例子就是典型的例子,此时值类型是内联在引用类型中。

    值类型嵌套引用类型时,该引用类型作为值类型成员的变量,将在堆栈上保留关引用类型的引用,但引用类型还是要在堆中分配内存的。

    (三)关于数组内存的分配

    考虑当数组成员是值类型和引用类型时的情形:

    成员是值类型:比如int[] arr = new int[5]。arr将保存一个指向托管堆中4*5byte(int占用4字节)的地址的引用,同时将所有元素赋值为0;

    引用类型:myClass[] arr = new myClass[5]。arr在线程的堆栈中创建一个指向托管堆的引用。所有元素被置为null。

   

 

二、值类型和引用类型在传递参数时的影响

    由于值类型直接将它们的数据存放在栈中,当一个值类型的参数传递给一个方法时,该值的一个新的拷贝被创建并被传递,对参数所做的任何修改都不会导致传递给方法的变量被修改。而引用类型它只是包含引用,不包含实际的值,所以当方法体内参数所做的任何修改都将影响传递给方法调用的引用类型的变量。可以用下面图来表示:

    下面程序证明了这一点: 

        
class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
      &n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值