A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 殘遛の丶狳味 中级黑马   /  2013-8-6 20:42  /  779 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

值类型和引用类型的区别?

评分

参与人数 1技术分 +1 收起 理由
赵宗荣 + 1

查看全部评分

6 个回复

倒序浏览
区别:
1、值类型通常被分配在栈上,它的变量直接包含变量的实例,使用效率比较高。

2、引用类型分配在托管堆上,引用类型的变量通常包含一个指向实例的指针,变量通过该指针来引用实例。

3、值类型继承自ValueType(注意:而System.ValueType又继承自System.Object);而引用类型继承自System.Object。

4、值类型变量包含其实例数据,每个变量保存了其本身的数据拷贝(副本),因此在默认情况下,值类型的参数传递不会影响参数本身;而引用类型变量保存了其数据的引用地址,因此以引用方式进行参数传递时会影响到参数本身,因为两个变量会引用了内存中的同一块地址。

5、值类型有两种表示:装箱与拆箱;引用类型只有装箱一种形式。我会在下节以专门的篇幅来深入讨论这个话题。

6、典型的值类型为:struct,enum以及大量的内置值类型;而能称为类的都可以说是引用类型。

7、值类型的内存不由GC(垃圾回收,Gabage Collection)控制,作用域结束时,值类型会自行释放,减少了托管堆的压力,因此具有性能上的优势。例如,通常struct比class更高效;而引用类型的内存回收,由GC来完成,微软甚至建议用户最好不要自行释放内存。

8、值类型是密封的(sealed),因此值类型不能作为其他任何类型的基类,但是可以单继承或者多继承接口;而引用类型一般都有继承性。

9、值类型不具有多态性;而引用类型有多态性。

10、值类型变量不可为null值,值类型都会自行初始化为0值;而引用类型变量默认情况下,创建为null值,表示没有指向任何托管堆的引用地址。对值为null的引用类型的任何操作,都会抛出NullReferenceException异常。

11、值类型有两种状态:装箱和未装箱,运行库提供了所有值类型的已装箱形式;而引用类型通常只有一种形式:装箱。

评分

参与人数 1技术分 +1 收起 理由
赵宗荣 + 1

查看全部评分

回复 使用道具 举报
这是当时的一道面试题。值类型在内存的一个地方存储它们自己和它们的内容。 引用类型存储指向内存中其他某个位置(称为堆)的引用,而在另一个位置存储内容。 值类型总是包含一个值,而引用类型可以是null,表示他们不包含值。但是,可以使用可空类型(这是泛型的一种形式)创建一个值类型,使值类型在这个方面的行为方式类似于引用类型(即可以为null)。
回复 使用道具 举报
1***、C#中有两种类型:
  值类型和引用类型:
     值类型的变量直接包含他们的数据,而引用类型的变量存储
引用类型存储对他们的数据的引用,后者称为对象:
     简单说:值类型直接存储其值,引用类型存储对值得引用.引用类型分为引用和引用的对象。
2***、
  值类型:简单类型、枚举、结构
  引用类型: 类类型、接口类型、数组类型和委托类型

3***、值类型与引用类型的内存存储
  单纯的说值类型存储在栈上,引用类型存储在托管堆上是不对的。
4***、区别:
  1、
    托管堆: 同步块和方法表, x,y,托管堆上的需要GC来回收
    线程堆栈: 没有同步块和方法表
  2、
    值类型赋值是重新创建一个副本
    而引用类型的赋值是共享同一块内存(副本),是指向同一块内存(引用类型的名字相当于指向操作)。只是复制引用而不复制被引用识别的对象。(“引用”和“引用的对象”)
  3、
    值类型与引用类型的不同之处就在于值类型的变量直接包括他们的数据,而引用类型的变量把references存储到他们的数据库(Objects)中。
  4、
    所有的值类型从Object中继承来的。任何类型都不能由值类型派生而来,因此,值类型是封闭式的。
  

5***什么时候使用值类型
    1)当类型是一个十分简单的类型,其中没有成员会修改类型的任何实例字段
    2)类型不需要从其他任何类型继承
    3)类型不会派生出其他任何类型
    4)类型的实例较小
    5)类型不作为方法参数传递,也不作为方法的返回类型使用
    6)引用类型可以包含null值,值类型不能(可空类型功能允许将null赋给值类型);

6***什么时候用ref和out
    ref:值类型在传递希望成为引用的时候,ref就是告诉传递的时候不是拷贝,而是同一个副本。
    out:不需要给变量赋初值,使用out也没必要在外面赋初值,是在内部赋“初值”,out传递值是理解成没有初始化的。
   
7***深度分析值类型和引用类型(内存中的部署)
    例子:Objectreference r = new object();
    关键字new在托管堆上分配内存空间,并返回一个该内存空间的地址。左边的reference位于栈上,是一个引用,存储着一个内存地址;而这个地址指向的内存(位于托管堆上)里存储着其内容。

    规律:
        1)引用类型部署在托管堆上
        2)值类型总是分配在它声明的地方:作为字段时,跟随其所属的实例存储。作为局部变量时,存储在栈上。
     总结: 引用类型在栈上存储一个引用,其实际的存储位置位于托管堆。

8***装箱与拆箱操作
    1) 装箱操作
       装箱(box)就是将值类型转换为引用类型的过程。而相反的过程就叫拆箱(unbox)。
       装箱时发生了什么?
           (1)在堆上分配内存。因为值类型最终有一个对象代表,所有堆上分配的内存量必须是值类型的大小加上容纳此对象及其内部结构(比如虚拟方法表)所需的内存量。
           (2)值类型的值被复制到新近分配的内存中
           (3)新近分配的对象地址被放到堆栈上,现在它指向一个引用类型。

    2)拆箱操作
       注:被装过箱的对象才能被拆箱。
       在装箱的时候,并不需要显示类型转换.但在拆箱时需要类型转换.这是因为在拆箱时对象可以被转换为任意类型.
       注意:装箱操作可以隐式进行,但拆箱操作必须显示。
       首先,检查这个对象实例,看它是否为给定值类型的装箱值。
       然后,把这个实例的值拷贝给值类型的变量。
   要尽量减少装箱与拆箱操作


9***问题
  1)C#中null和""的区别
    string是引用类型:
    string str= null 没有创建内存空间,str中存放的是空引用指针.
    string str="" str中存放的是指向堆中的指针。有指向

    简单地说:
       string str ="";
       给你一张白纸;
       string str = null;
       连白纸也没有。
    string.Empty就相当于""  一般用于字符串的初始化  
    判定为空字符串的几种写法,按照性能从高到低的顺序是:
s.Length == 0 优于 s == string.Empty 优于 s == ""  
  
   2)C#里面的垃圾回收  
      GC(垃圾回收)回收的都是可托管代码,也就是托管堆中的代码
      一般定义一个引用变量,它肯定会在堆上面占用一块空间,栈上有个地址指向这个存储位置,只有党GC发现堆上这个资源在栈上没有地址指向它的时候才把这块内存回收。
      非托管资源GC是不会自动回收的,例如数据库链接,文件等。

     

评分

参与人数 1技术分 +1 收起 理由
赵宗荣 + 1

查看全部评分

回复 使用道具 举报
1***、C#中有两种类型:
  值类型和引用类型:
     值类型的变量直接包含他们的数据,而引用类型的变量存储
引用类型存储对他们的数据的引用,后者称为对象:
     简单说:值类型直接存储其值,引用类型存储对值得引用.引用类型分为引用和引用的对象。
2***、
  值类型:简单类型、枚举、结构
  引用类型: 类类型、接口类型、数组类型和委托类型

3***、值类型与引用类型的内存存储
  单纯的说值类型存储在栈上,引用类型存储在托管堆上是不对的。
4***、区别:
  1、
    托管堆: 同步块和方法表, x,y,托管堆上的需要GC来回收
    线程堆栈: 没有同步块和方法表
  2、
    值类型赋值是重新创建一个副本
    而引用类型的赋值是共享同一块内存(副本),是指向同一块内存(引用类型的名字相当于指向操作)。只是复制引用而不复制被引用识别的对象。(“引用”和“引用的对象”)
  3、
    值类型与引用类型的不同之处就在于值类型的变量直接包括他们的数据,而引用类型的变量把references存储到他们的数据库(Objects)中。
  4、
    所有的值类型从Object中继承来的。任何类型都不能由值类型派生而来,因此,值类型是封闭式的。
  

5***什么时候使用值类型
    1)当类型是一个十分简单的类型,其中没有成员会修改类型的任何实例字段
    2)类型不需要从其他任何类型继承
    3)类型不会派生出其他任何类型
    4)类型的实例较小
    5)类型不作为方法参数传递,也不作为方法的返回类型使用
    6)引用类型可以包含null值,值类型不能(可空类型功能允许将null赋给值类型);

6***什么时候用ref和out
    ref:值类型在传递希望成为引用的时候,ref就是告诉传递的时候不是拷贝,而是同一个副本。
    out:不需要给变量赋初值,使用out也没必要在外面赋初值,是在内部赋“初值”,out传递值是理解成没有初始化的。
   
7***深度分析值类型和引用类型(内存中的部署)
    例子:Objectreference r = new object();
    关键字new在托管堆上分配内存空间,并返回一个该内存空间的地址。左边的reference位于栈上,是一个引用,存储着一个内存地址;而这个地址指向的内存(位于托管堆上)里存储着其内容。

    规律:
        1)引用类型部署在托管堆上
        2)值类型总是分配在它声明的地方:作为字段时,跟随其所属的实例存储。作为局部变量时,存储在栈上。
     总结: 引用类型在栈上存储一个引用,其实际的存储位置位于托管堆。

8***装箱与拆箱操作
    1) 装箱操作
       装箱(box)就是将值类型转换为引用类型的过程。而相反的过程就叫拆箱(unbox)。
       装箱时发生了什么?
           (1)在堆上分配内存。因为值类型最终有一个对象代表,所有堆上分配的内存量必须是值类型的大小加上容纳此对象及其内部结构(比如虚拟方法表)所需的内存量。
           (2)值类型的值被复制到新近分配的内存中
           (3)新近分配的对象地址被放到堆栈上,现在它指向一个引用类型。

    2)拆箱操作
       注:被装过箱的对象才能被拆箱。
       在装箱的时候,并不需要显示类型转换.但在拆箱时需要类型转换.这是因为在拆箱时对象可以被转换为任意类型.
       注意:装箱操作可以隐式进行,但拆箱操作必须显示。
       首先,检查这个对象实例,看它是否为给定值类型的装箱值。
       然后,把这个实例的值拷贝给值类型的变量。
   要尽量减少装箱与拆箱操作


9***问题
  1)C#中null和""的区别
    string是引用类型:
    string str= null 没有创建内存空间,str中存放的是空引用指针.
    string str="" str中存放的是指向堆中的指针。有指向

    简单地说:
       string str ="";
       给你一张白纸;
       string str = null;
       连白纸也没有。
    string.Empty就相当于""  一般用于字符串的初始化  
    判定为空字符串的几种写法,按照性能从高到低的顺序是:
s.Length == 0 优于 s == string.Empty 优于 s == ""  
  
   2)C#里面的垃圾回收  
      GC(垃圾回收)回收的都是可托管代码,也就是托管堆中的代码
      一般定义一个引用变量,它肯定会在堆上面占用一块空间,栈上有个地址指向这个存储位置,只有党GC发现堆上这个资源在栈上没有地址指向它的时候才把这块内存回收。
      非托管资源GC是不会自动回收的,例如数据库链接,文件等。

     
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马