本篇文章将以最简单易懂的方式介绍数据在堆区栈区和静态存储区中存放问题
一、什么是堆区和栈区
栈区 :先进后出,后进先出
堆区 :数据可以任意出入
区别:
栈空间比较小,但是读取速度快
堆空间比较大,但是读取速度慢
这也决定了数据在堆区和栈区存储类型、方式的不同
二、值类型与引用类型
在弄懂数据存储问题之前,明白值类型与引用类型也是必不可少的;
1、值类型存储问题
int c1 = 5;
int c2 = c1;
Console.WriteLine(c1);
Console.WriteLine(c2);
c1 = 6;
Console.WriteLine(c1);
Console.WriteLine(c2);
在这串代码中,首先定义一个整型变量(值类型)对象c1,并将c1的值赋给c2,输出结果为5,5;
后改变c1的值为6,输出结果为什么c2还是等于5呢?
定义的值类型c1,c2的值直接存放在栈区,并且同时享用一块内存区域
当c1被重新赋值后,系统会在栈区重新申请一块内存区域存放c1,此时c1,c2内存地址也相应的发生改变
2、引用类型存储问题
string c1 = "看完这篇文章";
string c2 = c1;
Console.WriteLine(c1);
Console.WriteLine(c2);
c1 = "肯定要三连!";
Console.WriteLine(c1);
Console.WriteLine(c2);
Console.ReadKey();
这里定义了一个string引用类型的变量c1 ,并将c1的值赋给c2,看起来和上述的值类型存储差不多,但其实引用类型和值类型存放的位置不同
与值类型不同的,变量c1与c2 会在栈区和堆区同时存放数据,栈区存放16进制地址指向存放在静态存储区的常量
当c1被重新赋值后,系统会在静态存储区重新申请一块内存区域存放c1的数据,此时c1,c2所指向的内存地址也相应的发生改变
3、对象引用的改变
namespace ConsoleApp1
{
class Question
{
string c1 ;
string c2 ;
public Question(string c1,string c2)
{
this.c1 = c1;
this.c2 = c2;
}
public void show()
{
Console.WriteLine(c1);
Console.WriteLine(c2);
}
public void Modify()
{
c1 = "没有看完这个视频";
c2 = "也要点赞!";
}
}
}
Question obj1 = new Question("看完这篇文章","肯定要点赞");
Question obj2 = obj1;
obj1.show();
obj2.show();
obj1.Modify();
obj1.show();
obj2.show();
从运行结果可以看出,这个例子与上述两个案例都不一样,当c1发生改变时,c2的值也随之发生改变
在对象的引用中,c1和c2共享一片内存单元,当c1调用Modify函数更改数据时 ,c1,c2也指向相同的一块地址区域