一、引用类型一定放在堆上吗?
面试官提到这个问题的时候,我第一反应当然说不是,然后我就说引用类型可能持有值类型的对象,而该对象存放在栈上……然后我开始觉得不妥……面试官接着问,那么在方法体结束后,栈上的临时空间释放了,那么该引用类型所持有的对象去哪里了呢……这时候意识到可能回答错误了,但是我就着这个问题回答,如果引用类型持有了某个值类型对象,那么会将其装箱在引用类型的堆内存中,当栈上空间释放后引用类型的值类型对象还是存在只不过其值为空……(那么该引用类型所持有的值对象不是一样在堆上了吗)
可能面试官就是想把我拉回到正确的答案上来,我的这一番回答也渐渐说明了一个问题:引用类型总是放在堆上的
引用类型就是总是在堆上的,而值类型的分配位置取决于他声明的位置,如果值类型声明在引用类型中,那么它就是在堆上的,如果在结构中,那么它就是分配在栈上的。
做一个简单的例子,如果我声明一个结构,结构中包含了引用类型,那么按照这样的操作,会输出什么?
struct Person
{
public CPerson cperson;
public int age;
public Sex sex;
public Person(int _age,Sex _sex)
{
age = _age;
sex = _sex;
cperson = new CPerson("CPerson");
}
}
class Program
{
public static void Main()
{
Person p1 = new Person(10,Sex.male);
Person p2 = p1;
p2.age = 12;
p2.cperson.name = "sperson";
p1.cperson.Print();
p2.cperson.Print();
Console.WriteLine(p1.age);
}
}
这里Sex是一个枚举类型。
结果输出:
sperson
sperson
10
这充分说明struct是值类型,像int一样赋值,在栈上新生成了对象,但是其中的引用类型,却只保留了其指针,指向了堆中的CPerson对象,所以最终的结果就是有两个Person的结构体对象,和一个CPerson引用类型对象,这两个结构中的cperson指针都指向这个堆中的对象。这就是一种浅拷贝。