引用变量即变量类型为引用类型的变量,在c#中,引用类型有class、interface、delegate。
class Student
{
}
Student stu; //引用变量
引用变量存储对实际数据(对象)的引用,而不是对象本身,也就是说引用变量存储的并不是实际的数据,而是实际的数据在内存中的地址。
与引用类型变量不同的是,值类型的变量存储的是实际的数据。
int a = 10; //a为值类型变量
int b = a; //b为值类型变量
在上面的代码中,a和b都是值类型的变量,存储的都是实际的数据,当将a赋值给b时,b会将a中的数据复制一份,存储下来。
class Student
{
public int Age;
}
Student stu = new Student(); //stu存储的是Student对象的内存地址
下面我将详细分析一下这几行代码在内存中干了哪些事。
Student stu; //声明一个引用变量
这条语句会在内存中开辟一块区域,用于存储引用变量的值,引用变量占内存大小为4个字节。当然,现在只进行了变量的声明,并没有为它赋值,所以此时stu指向一个空引用null,在内存中表现为每一位都为0。
Student stu = new Student(); //将Student对象的内存地址给stu引用变量
我们前面说过,引用变量存储的并不是实际的数据,而是对实际数据的引用。
这一行代码可以分解为两部分:
new Student(); //创建类的实例
Student stu = new Student(); //赋值
new Student();会在内存中开辟一片区域,用来存储实例的数据,我们知道,在c#中,int类型的变量占4个字节。这里我们没有为Age显式的赋值,默认构造器会为其赋值为0。
Student stu = new Student();这一行代码将对象的内存地址赋给stu,也就是说stu存储的是对象的内存地址这一串数字的二进制表示。当我们使用stu去访问和操作Student对象的成员时,会先通过stu变量中存储的内存地址,去找到存储实际数据的内存到底在哪里,然后再进行访问和操作。
当然,一个对象也可以被多个引用变量引用。
class Student
{
public int Age;
}
Student stu1 = new Student();
stu1.Age = 10;
Console.WriteLine(stu1.Age)
Student stu2 = stu1;
stu2.Age = 20;
Console.WriteLine(stu1.Age)
//输出结果为:
//10
//20
在上面的代码中,stu1和stu2存储的都是Student类的实例的内存地址,也就是说,stu1.Age=10和stu2.Age=20都是对同一个内存中的数据进行操作。
与之不同的是,值类型的变量存储的是实际的数据,而不是对实际数据的引用。
public struct Student
{
public int Age;
}
Student stu1;
stu1.Age = 10;
Console.WriteLine(stu1.Age);
Student stu2 = stu1;
stu2.Age = 20;
Console.WriteLine(stu1.Age);
//输出结果为:
//10
//10
在上面的代码中,stu1和stu2存储的值位于不用的内存,所以两者互不影响。