值类型跟引用类型

做功能性开发甚至架构设计久了,往往会忽略了对基础只是的总结与学习,而基础知识掌握的精通与否,其实很大程度上影响着代码的逻辑深层机制,是解决机制的而非逻辑的问题,这篇我详细研磨下值类型跟引用类型。

既然要研磨值类型跟引用类型,则必然逃不过堆栈,那么堆、栈、堆栈到底是什么呢?我们应该怎样理解堆栈呢?

计算术语:

堆:堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。存放在二级缓存,生命周期由虚拟机的垃圾回收算法来决定,所以调用这些对象的速度相对来说要些,由程序员分配释放,分配方式类似链表。

栈:栈(stack)又名堆栈,它是一种运算受限的线性表先进后出,其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。使用一级缓存调用完立即释放。由操作系统自动分配释放,类似数据结构中栈。

堆栈:什么是堆栈?又该怎么理解呢?其实堆栈本身就是,只是换了个抽象的名字。后进先出(LIFO)队列

上面是关于堆、栈的一些基本定义及区别,下面做一些详细的比较:

堆:

①堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
  ·堆中某个节点的值总是不大于或不小于其父节点的值;
  ·堆总是一棵完全二叉树。
   将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
②堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。
③堆是应用程序在运行的时候请求操作系统分配给自己内存,一般是申请/给予的过程。
④堆是指程序运行时申请的动态内存,而栈只是指一种使用堆的方法(即先进后出)。

栈:

①栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。

②栈就是一个桶,后放进去的先拿出来,它下面本来有的东西要等它出来之后才能出来(先进后出)

③栈(Stack)是操作系统在建立某个进程时或者线程(在支持多线程的操作系统中是线程)为这个线程建立的存储区域,该区域具有FIFO的特性,在编译的时候可以指定需要的Stack的大小。

堆、栈区别总结:

1.堆栈空间分配 

 ①栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

 ②堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。

2.堆栈缓存方式 

①栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。

②堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

3.堆栈数据结构区别 

①堆(数据结构):堆可以被看成是一棵树,如:堆排序。

②栈(数据结构):一种先进后出的数据结构。

 

开始引用正题,到底什么是值类型、什么是引用类型呢?

1.通用类型

C#中,变量是值还是引用取决于其数据类型。

C#的基本数据类型都以平台无关的方式来定义。C#的预定义类型并没有内置于语言中,而是内置于.NET.Framework中。.NET使用通用类型(CTS)定义了可以在中间语言(IL)中使用的定义数据类型,所有面向.NET的语言都最终被编译成IL,即编译为基于CTS类型的代码。

例如,在C#中声明一个int变量时,声明的实际上是CTS中System.Int32的一个实例。这具有重要的意义

      ※ 确保IL上的强制类型安全;

      ※ 实现了不同.NET语言的互相操作性;

      ※ 所有的数据类型都是对象。它们可以有方法,属性、等,例如:

int i;
i = 1;
string s;
s = i.ToString();

一下关系图,说明了这几种数据类型是如何相关的。注意,类型的实例可以只是值类型或自描述类型,即使这些类型有子类别也是如此。

类型的类别:

2.值类型

C#的所有值类型均隐式派生自System.ValueType;

结构体:struct(直接派生于System.ValueType)

可空类型:派生于System.Nullabe<T>泛型结构体,T?实际上是System.Nullabel<T>的别名。

decimal型:用于财务计算的高精度decimal型:decimal(System.Decimal)

每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。例如:

            int i = new int();
            //等价于
            Int32 i = new Int32();//引用System
            //等价于
            int i = 0;
            //等价于
            Int32 i = 0;

 

引用类型和值类型都继承自System.Object类。不同的是,几乎所有的引用类型直接从System.Object继承,而值类型继承子类,及System.ValueType,System.Object直接派生于System.Object。即System.ValueType本身上一个类型,而不是值类型。其关键在于ValueType重写了Equals()方法,从而对值类型按照实例的来比较,而不是引用地址来比较。

 

3.引用类型

C#有以下引用类型:

可以看出:

引用类型与值类型相同的是,结构体也可以实现接口

引用类型可以派生出新的类型,而类型不能

引用类型可以包含null值类型不能(可空类型功能将null赋值给值类型);

引用类型变量的赋值只复制对象的引用,而不是复制对象本身。而将一个值类型变量赋给另一个值类型变量时,将复制包含的

string在实际的使用中,让人很容易误以为复制了值,就像值类型一样,实际上.NET对string类型做了享元处理。

 

posted @ 2018-11-30 20:50  <--青青子衿-->  阅读(169)  评论(0编辑  收藏  举报
// /**/ // 在页脚Html代码 引入 // function btn_donateClick() { var DivPopup = document.getElementById('Div_popup'); var DivMasklayer = document.getElementById('div_masklayer'); DivMasklayer.style.display = 'block'; DivPopup.style.display = 'block'; var h = Div_popup.clientHeight; with (Div_popup.style) { marginTop = -h / 2 + 'px'; } } function MasklayerClick() { var masklayer = document.getElementById('div_masklayer'); var divImg = document.getElementById("Div_popup"); masklayer.style.display = "none"; divImg.style.display = "none"; } setTimeout( function () { document.getElementById('div_masklayer').onclick = MasklayerClick; document.getElementById('btn_donate').onclick = btn_donateClick; var a_gzw = document.getElementById("guanzhuwo"); a_gzw.href = "javascript:void(0);"; $("#guanzhuwo").attr("onclick","follow('33513f9f-ba13-e011-ac81-842b2b196315');"); }, 900);