1、在讲堆和栈之前,我们先看看值类型和引用类型:
(1)值类型
A:基本数据类型
a:int:整型
b:long:长整型
c:float:浮点型
d:char:字符型
e:bool:布尔型
B:枚举类型
枚举:enum
C:结构类型
结构:struct
(2)引用类型
A:类
a:基类:System.Object
b:字符串:string
c:自定义类:class
B:接口
接口:interface
C:数组
数组:int[],string[]
2、值类型和引用类型的存储方式
值类型:值类型总是分配在它声明的地方,作为局部变量时,存储在栈上;类对象的字段时,则跟随这个类存储在堆中。
引用类型:引用类型存储在堆中。类型实例化的时候,会在堆中开辟一部分空间存储类的实例。类对象的引用还是存储在栈中。
Class Program
{
static void Main(string[] args)
{
//s:对象的引用【存储在栈中】
//new Student()【对象存储在堆中】
Student s=new Student();//引用类型
//局部变量【存储在栈中】
int a =1;//值类型
}
}
class Student
{
//类的字段【跟随这个类存储在堆中】
public int Age=1;//值类型
}
3、引用类型和值类型的不同
(1)引用类型和值类型都继承自System.Object类。不同之处,几乎所有的引用类型都是直接从System.Object继承,而值类型则是继承System.Object的子类System.ValueType类。
(2)我们在给引用类型的变量赋值的时候,其实只是赋值了对象的引用;而给值类型变量赋值的时候是创建了一个副本(即克隆了一个变量)。
Class Program
{
static void Main(string[] args)
{
//引用类型赋值
Student s=new Student();
s.Age=10;
Student s2=s;//给引用类型的变量赋值的时候,其实只是赋值了对象的引用
s2.Age=20;
Console.RriteLine(s.Age);//20
//值类型赋值
int a =0;
int a2=a;//给值类型变量赋值的时候是创建了一个副本
a2=10;
Console.WriteLine(a);//0
}
}
class Program
{
public int Age=0;
}
4、引用类型和值类型的内存分配情况
class Program
{
static void Main(string[] args)
{
int i=10;//int类型在栈中占了4个字节
Student s=new Student();//一个对象的引用在栈中占了4个字节
long j=10;//long类型在栈中占了8个字节
}
}
class Student
{
public int Age1=10;
public int Age2=20;
}
总结:栈的结构是先进后出;栈地址从高往低分配;类型的引用也存储在栈中