目录
值类型
值类型的储存只需要一段储存 用来存放实际的数据 在栈中储存
int a = 10;
引用类型
需要两段内存
第一段(等式前)储存实际的数据 它在栈中储存
第二段(等式后) 是一个应用指针,指向数据在堆内存中储存数据的位置地址储存在栈中 通过栈中的地址快速的找到堆中的数据
对象与对象之间不会相互影响 通过new出来的对象都会在堆内存中开辟一块新的空间
class Student
{
public int age;
public string name;
public Student(int age, string name)
{
this.age = age;
this.name = name;
}
}
static void Main(string[] args)
{
Student stu = new Student(20,"小明");
Student stu1 = new Student(30,"李四");
}
修改stu3的值 stu也被修改了 为什么? (对象之间)
因为将stu中存储的地址赋值给了stu3 它们两个是共用的一个地址 指向同一个堆内存 所以一个修改另外一个也会修改
Student类的对象之间,栈中的 stu3 = stu(stu3没有使用new重新开辟一块新的空间 ),其地址指向同一个堆内存中储存的数据
Student stu3 = stu; stu3.age = 100; Console.WriteLine(stu3.age);//100 Console.WriteLine(stu.age); // 20? 100? 输出为100
null 空 空对象 空引用 空对象会被垃圾回收机制回收(GC)
栈内存空间小 读取速度快
堆内存空间大 读取速度慢
值类型中,值全在栈中单独存储,变量之间不会影响
int num = 10;
int num1 = num;
num = 20;
Console.WriteLine(num); //20
Console.WriteLine(num1);//10
结构体中,结构体全在栈中,结构体与结构体之间也不会相互影响
static void Main(string[] args)
{
//结构体全在栈中
Dog d1 = new Dog("阿黄",2);
Dog d2 = new Dog();
// 结构体与结构体之间不会相互影响
d1.age = 100;
Console.WriteLine(d1.age);
Console.WriteLine(d2.age);
Dog d3 = d1;
d1.age = 1000;
Console.WriteLine(d1.age); // 1000
Console.WriteLine(d3.age); // 2
}
struct Dog
{
public string name;
public int age;
//结构体即使 自己定义了 有参的构造函数 默认的无参的也会存在,如定义的 d2,但是类中会被覆盖
public Dog(string name, int age)
{
this.name = name;
this.age = age;
}
}
在结构体中,即使自己定义了 有参的构造函数 默认的无参的也会存在,如定义的 d2,但是类中会被覆盖,若使用无参的还得再定义一个无参的构造函数。
静态资源区
对于字符串常量来说 实际是储存在静态资源区的 即使在堆中用的字符串也是存放在静态资源区的 因为 如果用到重复的字符串时 他们指向的地址是一样的 会解决内存问题 字符串在静态资源区中是不会被改变的 看到的修改其实只是修改指向的位置 内容并没有修改
const string name = "小明";//const 定义常量