<From C++ To C#> 我们先定义一些局部变量
static void Main(string[] args) { int i = 1; bool b = true; char c = 'a'; float f = 0.1f; double d = 0.2; }
这段看似和C++一模一样的局部变量定义代码,其实内部运行的方式有很大的差异。这些int, double不再是以往简单的内建类型,而是C#数据类型的别名。
我们看一下CTS规定的,也就是C#所遵循的系统类型层次结构。
如图所示C#语言是单根的。也就是说所有的类型都集成于一个类,这个类叫做System.Object。所有直接继承于System.Object的类,都叫做引用类型。所有继承于ValueType,并间接继承于System.Object叫做值类型。我们刚才所用的这些类型都是值类型。在图上蓝色表示。
前面说过,C#很注重命名规范,所以这些值类型其实都有他们的“大名”。bool其实叫System.Boolean,int其实叫System.Int32。你看,他们都属于System的命名空间,而且类型的首字母都是大写。不过实际上,大家都喜欢用他们的“小名”,bool, int来称呼他们,这样会感觉更亲切一些。
那么值类型和引用类型到底有什么区别呢。我们学C++的都知道,系统运行起来后,变量都保存在内存中。普通的局部变量保存在叫做“栈”的内存块中,通过遇到{入栈,}出栈的操作,系统可以自动维护局部变量的生命周期。而我们new出来的变量都保存在“堆”中,创建在“堆”中的内存块只能通过我们自己来释放,所以一再强调有new必然要有对应的delete。
在C#中的定义是这样的:所有的值类型都保存在栈中,所有的引用类型都保存在堆中。也就是说,我们刚才定义的int, double,因为他们都是值类型,保存在栈中,所以他们都会在函数结束的时候被系统自动释放掉。而如果我们申明一个字符串或者数组,因为他们是引用类型,保存在堆中,所以函数结束的时候并不会自动释放。而是等待delete被释放。
我们再来搞一下脑子。有这样一段代码
double d = new double();
1)这段代码可行么?2)函数结束时d变量是否还存在在内存中?
首先,这段代码是可行的!double是System.Double类型的简称,new这样一个类型肯定没问题(*注意,C++中只能写成new double, 后面的括号只有在构在函数需要参数的时候才要加上。)
其次,d变量在函数结束时会被自动销毁。虽然它看起来是用了new,但是由于它是值类型,而值类型是保存在栈中的,所以即使看着奇怪,他仍然会被退栈。
值类型引用类型是CTS的根基,很重要!好了,今天就说到这里。