请看下面代码
请看下面代码
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string sr1 = "张三";
sr1 = "王五";
string sr2 = sr1;
sr2 = "李四";
Console.ReadKey();
}
}
}
这个代码很简单,但是C#的内存 是怎么做的呢。
首先要明确一点 C#的值类型和引用类型。 值类型 包括 int double char decimal bool struct enum 存于栈上
引用类型包括 string ,自定义类,接口,集合,数组。存在堆上。
值类型的传递时候,是在栈上开辟一块内存,让后将值复制过去,int i=10; int m=i; 是在栈上开辟内存m, i,把i中的值10 复制到m的内存中。
引用类型传递时, 是在对上开辟一块内存,建立对象,在栈上也开辟一块内存用来存放堆上对象的地址。例如 stduent a=new stduent ()-----在堆上开辟空间存放stduent 对象,在栈开辟一块内存a 存stduent 堆上对象的地址。stduent b=a;时,这时候是在栈开辟空间b ,将a内的内容复制到b中。这样b也指向a的那块内存了。操作b改变stduent 对象的成员会改变对上的值,a去使用时,对象的值也会相应的改变,因为是同一块内存。
对于字符串string 有一个不同点。就是字符串的不可变性。代码中
string sr1 = "张三";这时 栈上存sr1 指向堆上的"张三"的地址。
string sr1 = "王五";
这时 栈上存sr1 指向堆上的"王五"的地址。但是"张三"的内存没有消亡 我们不禁要问这样的内存什么时候回回收,系统有个GC的垃圾回收器,当张三的所有引用都没有的时候。当没有指向张三的这款内存时,GC会回收。
在程序中打两个断点就可以很清楚的看出问题。
蓝色圈是sr1,sr2的栈上的内存地址,红色圈是sr1,sr2的栈上地址