从栈和堆中来看值传递和引用传递
来源:互联网 发布:flac播放软件 编辑:程序博客网 时间:2024/06/01 19:21
1 栈和堆
1.1 栈
栈是一个内存数组,是一个LIFO(Last-In First-Out,后进先出)的数据结构。
栈存储几种类型的数据:
某些类型变量的值;
程序当前的执行环境;
传递给方法的参数。
栈有如下几个特征:
数据只能从栈的顶端插入和删除。
把数据放到栈顶称为入栈(push)。
从栈顶删除数据称为出栈(pop)。
栈是在编译期,由编译器分配好内存空间。
1.2 堆
堆是一块内存区域,在堆中可以分配大块的内存用于存储某类型的数据对象。
与栈不同,堆里的内存能够以任意顺序存入和删除。
堆是在运行期,根据程序运行情况动态分配内存空间。
2 值类型和引用类型
C#数据类型分为两种:值类型和引用类型,这两种类型的对象在内存中的存储方式不同。
值类型:只需要一段单独的内存,用于存储实际的数据。
引用类型:需要两段内存。
第一段存储实际的数据,它总是位于堆中。
第二段是一个引用,指向数据在堆中的存放位置。
一般情况下,对于值类型,数据存放在栈里。对于引用类型,引用存放在栈里,实际数据存放在堆里。如图所示:
当然,上面是一般情况,值类型数据或引用类型的引用部分也会存放在堆中。
比如,当一个值类型或一个引用类型是另一个引用类型对象的数据时,便会存放在堆中。
C#中的值类型和引用类型如图所示:
3 值参数和引用参数(值传递和引用传递)
值参数:通过将实参的值复制到形参的方式把数据传递给方法。方法被调用时,系统在栈中为形参分配空间,然后将实参的值复制给形参。
引用参数:在参数前面加 ref 或 out 修饰符 ,实参必须是变量。
ref 和 out 的区别:ref参数传入方法之前必须初始化;out参数不需要,但out参数在方法返回时必需赋值。
3.1 值类型数据作为值参数传递
using System;namespace Test{ class Program { static void Main(string[] args) { int val = 10; MyMethod(val); Console.WriteLine("val的值为:{0}",val); } static void MyMethod(int xxx) { xxx = xxx + 5; Console.WriteLine("xxx的值为:{0}",xxx); } }}
结果如图所示:
分析如图所示:
3.2 值类型数据作为引用参数传递
using System;namespace Test{ class Program { static void Main(string[] args) { int val = 10; MyMethod(ref val); Console.WriteLine("val的值为:{0}",val); } static void MyMethod(ref int xxx) { xxx = xxx + 5; Console.WriteLine("xxx的值为:{0}",xxx); } }}结果如图所示:
分析如图所示:
3.3 引用类型数据作为值参数传递
写了两个例子,注意在方法内部形参p的不同之处!
示例1:
using System;namespace Test{ class Program { static void Main(string[] args) { Person p1 = new Person(); p1.name = "lzj"; MyMethod(p1); Console.WriteLine("p1.name的值为:{0}",p1.name); } static void MyMethod(Person p) { p.name = "CR7"; Console.WriteLine("p.name的值为:{0}",p.name); } } class Person { public string name; }}结果如图所示:
分析如图所示:
示例2:
using System;namespace Test{ class Program { static void Main(string[] args) { Person p1 = new Person(); p1.name = "lzj"; MyMethod(p1); Console.WriteLine("p1.name的值为:{0}",p1.name); } static void MyMethod(Person p) { p = new Person() { name = "CR7" }; Console.WriteLine("p.name的值为:{0}",p.name); } } class Person { public string name; }}结果如图所示:
分析如图所示:
3.4 引用类型数据作为引用参数传递
using System;namespace Test{ class Program { static void Main(string[] args) { Person p1 = new Person(); p1.name = "lzj"; MyMethod(ref p1); Console.WriteLine("p1.name的值为:{0}",p1.name); } static void MyMethod(ref Person p) { p = new Person() { name = "CR7" }; Console.WriteLine("p.name的值为:{0}",p.name); } } class Person { public string name; }}结果如图所示:
分析如图所示:
总结
作为值参数(即值传递)时:传递的是栈中的数据。
作为引用参数(即引用传递时):传递的是栈本身的地址。
- 从栈和堆中来看值传递和引用传递
- "栈"和"堆"的区别; 引用传递和值传递
- JAVA中参数传递(按值传递和引用传递)
- js 中参数传递(值传递和引用传递)
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 引用传递和值传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- 值传递和引用传递
- leecode 解题总结:70. Climbing Stairs
- THUWC2017 酱油记
- boost处理日期和时间的总结
- 【JSOI2015】送礼物
- Servlet3.0包依赖问题
- 从栈和堆中来看值传递和引用传递
- Linux 常用环境变量及作用和环境变量文件的详细介绍及其加载执行顺序
- PAT甲级真题1012. The Best Rank (25)
- 自然语言处理与深度学习: 集智俱乐部活动笔记
- 【bzoj1878】HH的项链(莫队)
- Oracle数据库的整理——2基础概念
- 阿里云CentOS 7.1使用yum安装MySql5.6.24
- 状压dp训练
- docker