C# 形参 实参 调用时在托管栈和托管堆中的分配情况

每每看到别人写的文章,总觉得冗长,不够简练,作为1个开发我们要力求简洁明了,当然人非圣贤孰能无过,我写的也不是尽善尽美,我尽我所能保证每一句随笔的正确性,期间我会参考很多来源的资料,当然也会在文章最后列出原博客地址,如果你觉得我写的不够清楚,那么你可以参考这些地址做详细阅读。

作者本身也是很愿意和大家一起交流技术,如果你看了我的文章中间有不同的论断和见解,那么你可以在下方留言,作者看到留言都会回复,一起探讨.NET技术。

以下内容来源于网络加自己的认同的理解,和自己认为一些重要的东西。

CLR数据类型: 值类型(Value Type)和引用类型(Reference Type)

值类型:int、char、float、long、bool、double、structenum、short、byte、decimal、sbyte、uint、ulong、ushort等

引用类型:stringclass、interface、delegate、object等

 

对于如下代码:

int myAge = 19;

Student myStu = new Student("唐马儒", 20);

public void test(int age, Student stu);

test(myAge, myStu);

 

函数定义了形参,当真正调用函数的时候,传递的参数就是实参。

对于基本值类型,默认情况下是传递值的拷贝,在栈中会开辟一块内存,拷贝myAge的值到为栈中名称为age的地址中去,对于Student类的实例,内存只需要在栈中创建了1个指针。放在名称为stu的地址空间中,指向heap中的学生对象,栈中名称为myStu内的Pointer也指向heap中的学生对象。

思考:1. 如果形参和实参的名称相同,那么在栈中重新开辟内存空间的时候,新空间的名称叫什么?

但是C#提供了ref和out修饰符来修饰函数参数,如果遇到了这2种情况(ref一般是加在值类型前面,因为加在引用类型前面没有意义),调用函数就不会再栈中重新开辟一块内存来存放age这个值,而是把myAge的地址传递给调用内部,这样在调用内部对变量的修改就会反映到外部代码,这个过程中没有装箱(boxing)和拆箱(unboxing)。

附加1个知识点:

1. C#对于引用类型实例对象的值类型成员与对象一起存放在heap中

2. 对于值类型(比如结构体)中的引用类型的创建的对象是保存在heap中,stack中仅保留这个对象成员的引用(也叫指针 Pointer)

 

C#有1条黄金规则:

1. 所有引用类型都是放在heap中

2. 值类型和指针总是放在它们被声明的地方

 

参考资料:

1. 百度知道-C#中的引用类型和值类型有哪些

2. C#中的ref, out, params修饰符+引用类型和值类型说明

3. 图解C#中的实参和形参是怎么分配内存的

4. AnyTao-你必须知道的.NET之内存剖析

5. 栈,堆,静态区,常量区的内存分配图解

6. IL代码怎么看懂

posted @ 2014-04-06 01:12  Thirty  阅读(485)  评论(0编辑  收藏  举报