栈和堆
运行中的程序用两个内存区域来储存数据,栈和堆
栈
栈(Stack):快速、小型,用于存储短生命周期的简单数据(如值类型和引用的指针)。
栈是一个内存数值讲究后进先出的数据结构储存几种类型的数据
1.某些类型变量的值
2.程序当前的执行环境
void Example1()
{
int x = 1; // 局部变量 x 存储在栈中
Example2(x); // 方法调用时,将 x 的值(1)传递并压入栈中
}
void Example2(int y)
{
int z = y + 5; // 局部变量 y 和 z 存储在栈中
}
z=1+5=6
3.传递给方法的参数
void AddNumbers(int a, int b)
{
int result = a + b; // 参数 a 和 b,以及局部变量 result 都存储在栈中
}
void Example1()
{
AddNumbers(5, 10); // 调用方法时,5 和 10被压入栈中作为参数
}
栈只能从顶部插入和删除,入栈(push)和出栈(pop)
类似叠木块,叠好后从最上面的开始拿走
堆
堆(Heap):灵活、大型,用于存储更复杂、长生命周期的数据(如对象和引用类型)。
堆可以分配大块的内存储存对象,堆能任意存入和移除内存,当不再访问某数据时,
自动垃圾收集器会自动清理
决定储存方式栈或堆
预定义类型 | sbyte , short , int , long , byte , ushort , uint , ulong ,bool | float , double , char , decimal , object , string , dynamic |
用户定义类型 | struct , enum | class , interface , delegate , Array |
值类型只需要一段单独的内存,用于储存实际数据,值类型数据储存在栈里
1.值类型:
int a = 10; // 栈中存储了变量 a,值为 10
int b = a; // 栈中分配了另一个独立的变量 b,值也为 10
b = 20;
Console.WriteLine(a); // 输出:10(a 和 b 互不影响)
引用类型需要两段内存
2. 引用类型:
MyClass obj1 = new MyClass { }
引用类型的对象的数据部分始终存放在堆里 new堆内存堆(Heap)中分配一块空间
第一段储存实际数据,引用类数据总是位于堆中
第二段是一个引用,从栈中指向数据在堆中的位置 ,引用(变量)放在栈中
自动初始化
变量类型 存储位置 自动化
局部变量 栈或堆 否 用于函数局部计算
类字段 堆 是 类的成员
结构字段 栈或堆 是 结构的成员
参数 栈 否 用于值传入传出的方法
数组元素 堆 是 数组的成员
1.局部变量
void Example()
{
int a; // 局部变量未初始化
Console.WriteLine(a); // 编译错误:使用了未赋值的局部变量
}
2.类字段
class MyClass
{
public int Number; // 自动初始化为 0
public string Text; // 自动初始化为 null
}
void Example()
{
MyClass obj = new MyClass();
Console.WriteLine(obj.Number); // 输出:0
Console.WriteLine(obj.Text); // 输出:null
}
值类型:如 int
默认值为 0
,bool
为 false
。
引用类型:如 string
默认值为 null
。
3.结构字段
结构体的字段会根据结构体的存储位置(栈或堆)被自动初始化。
struct MyStruct
{
public int Number; // 自动初始化为 0
}
void Example()
{
MyStruct myStruct = new MyStruct(); // 实例化结构
Console.WriteLine(myStruct.Number); // 输出:0
}
4.参数
void MyMethod(int value)
{
Console.WriteLine(value); // 必须有一个明确的初始值
}
MyMethod(10); // 调用时传入值
当// MyMethod(10); // 编译器报错:没有提供参数
5.数值元素
正常赋值 :
int[] numbers = new int[3]; // 创建数组,默认值为 [0, 0, 0]
numbers[0] = 10; // 显式赋值
numbers[1] = 20;
numbers[2] = 30;
Console.WriteLine(string.Join(", ", numbers)); // 输出:10, 20, 30
初始化:
int[] numbers = new int[3]; // 创建一个长度为 3 的数组
Console.WriteLine(numbers[0]); // 输出:0(自动初始化)