.net框架读书笔记---值类型与引用类型(一)

接上一篇.net框架读书笔记---委托(一),最近看到园子里面有好多关于值类型和引用类型的讨论,自己这几天也看书学习了一下,CLR支持两种类型:引用类型和值类型,我们和引用类型打交道的机会最多,引用类型总是从托管堆上分配,C#中new操作符返回的就是对象位于托管堆中的内存地址----该内存地址指向对象占用的数据位,使用引用类型时,我们需要注意以下事实:

  • 内存必须从托管堆上中分配。
  • 每一个托管堆中分配的对象都有一些与之关联的额外附加成员被初始化
  • 从托管堆中分配对象可能会导致执行垃圾收集

  所以说引用类型的性能是比较低的,为了提高那些简单操作,常用类型的性能,clr提供了值类型,值类型通常分配在线程的堆栈上(虽然它们也可以被嵌入到一个引用类型的对象中,注:这时他们也分配在托管堆中)。表示值类型实例变量不包含指向实例的指针---变量本身即包含了实例所有的字段,因为变量本身包含了实例所有的字段,所以操作实例时也就无需再解析指针引用。值类型实例不受垃圾回收器的控制,因此也减少了托管堆的压力,以及应用程序在整个生存期中需要垃圾回收的次数。所有的值类型都必须继承自System.ValueType;

  

  说一下线程堆栈和托管堆的区别:

  线程堆栈(Thread Stack):所有值类型的变量都是在线程堆栈中分配的。

    每个正在运行的程序都对应着一个进程(process),在一个进程内部,可以有一个或多个线程(thread),每个线程都拥有一块“自留地”,称为“线程堆栈”,大小为1M,用于保存自身的一些数据,比如函数中定义的局部变量、函数调用时传送的参数值等,这部分内存区域的分配与回收不需要程序员干涉。

 

  托管堆(heap):所有引用类型变量所引用的对象,其内存都市在托管堆中分配的。
另一块内存区域称为“堆(heap)”,在.NET这种托管环境下,堆由CLR进行管理,所以又称为“托管堆(managed heap)”。托管堆中的内存资源是可以动态申请并使用的,但是用完了必须归还;

下面的代码展示了引用类型和值类型之间的一下差别:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
// 引用类型
class SomeRef
{
public int x;
}

// 值类型
struct SomeVal
{
public int x;
}

static void Main( string [] args)
{
SomeRef r1
= new SomeRef(); // 分配在托管堆上
SomeVal v1 = new SomeVal(); // 分配在堆栈上

r1.x
= 5 ; // 解析指针
v1.x = 5 ; // 在堆栈上修改
//该赋值过程如图一

Console.WriteLine(r1.x);
// 5
Console.WriteLine(v1.x); // 5
 

SomeRef r2
= r1; // 仅仅拷贝指针,这个时候r2和r1是指向同一快内存的
SomeVal v2 = v1; // 现在堆栈上分配,然后拷贝成员
 
 
//该赋值过程如图二  

Console.WriteLine(r1.x);
// 8
Console.WriteLine(r2.x); // 8
Console.WriteLine(v1.x); // 9
Console.WriteLine(v2.x); // 5

}

r1.x
= 8 ; // 改变了r1.x和r2.x
v1.x = 9 ; // 改变了v1.x没有改变v2.x
 
   

图一

2010040121365661.jpg

图二

2010040121371474.jpg

呵呵图比较粗糙

以上代码中 SomeVal v1=new SomeVal();, 该行代码编写的方式看起来很像在托管堆上分配了一个SomeVal实例,然而C#编译器知道它是一个值类型,因此会分配在线程的堆栈上;上面代码也可以这样子写:

SomeVal v1;这个两者的主要差别是如果使用了new操作符,那么C#将认为实例已经得到了初始化,看看下面的代码:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
// 下面两行能够编译通过,C#认为v3的字段首先被初始化为0
SomeVal v3 = new SomeVal();
int a = v3.x;

// 不能通过,v4的字段没有经过初始化
SomeVal v4;
int b = v4.x; // error:错误 1 使用了可能未赋值的字段“x”

值类型不能被继承,不能定义虚方法,不能定义抽象方法;

值类型之间的赋值时“字段对字段”的拷贝,引用类型之间只是引用的拷贝,指向同一快内存 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值