我在理解.net框架中引用和值类型之间的区别时遇到了一个小问题。你可能会说这是每个程序员应该知道的基本差异,而且我相信会知道这种不同之处,但有时会发生在某些书籍中对这个问题有不同的看法。
我知道.NET是一个托管环境,垃圾收集器存在并运行。数据和结构存储在两个主要位置:托管堆和堆栈。
托管堆应该充当所有指向驻留在堆栈中的实际数据的指针的容器。这就是我所知道的以及Dino Esposito关于.NET的书中解释的内容(谈论vb.net)。 是这样吗?或者有些事情不正确?
我还有另一个问题...... 或者更好,我需要确认我的想法...
当我在c#
中写这样的东西时string mystring = "Hello World!";
我认为CLR在堆栈中创建一个字符串数据,并在堆中创建指向该数据的指针。 如果我这样做:
mynamespace.someprintfunction(mystring);
CLR检索“Hello World!”会发生什么?通过查看mystring(堆中的指针到堆栈中的数据)。
此外,鉴于字符串是不可变的,如果我这样做:
string mystring2 = "Hello World!";
CLR不会在堆中创建新的指针mystring2和“Hello World!”的记录。在堆栈中,但它使用预先存在的“Hello World!”由mystring指出并创建一个新指针。 结果是mystring和mystring2指向堆栈中的相同位置。
答案 0 :(得分:3)
你混淆了堆和堆栈。如果创建引用类型的实例,通常会在堆上分配此类的内存,并在堆栈上获得指向该数据的引用/指针。
关于值和引用类型之间的区别,有人说值类型存储在堆栈上的堆栈和引用类型上,但这并不总是正确的(同样,它是CLR的实现细节,在大多数情况下也无关紧要为用户)。
最重要的区别是,值类型按值传递 (在分配时将整个数据复制到另一个变量中),引用类型按引用(您仅复制对原始数据的引用)。
所以当你执行int x = 5; int y = x;
时,你正在复制x的值。 x和y不是指相同的数据。
另一方面,如果对引用类型的实例执行相同操作,则两个变量都引用同一对象。
答案 1 :(得分:1)
并非所有所谓的“真实数据”都存在于堆栈中 例如:
public static void Main()
{
int a = 5;
int[] arr = new int[20];
}
a
是一个值类型,它的4个字节在堆栈上,而arr
是指向堆分配内存的指针,arr
本身(指针)在堆栈上但是实际的数组数据(即使它是一个整数的数组)正在堆上分配。
修改强>
关于你的第二个问题
1.字符串文字保存在特殊位置,因此两个字符串变量将指向同一个对象
当你执行string mystring = "Hello World!";
时,mystring将指向字符串文字,并且在调用方法时,指向字符串的指针将作为方法参数被推送到堆栈。