从栈和堆中来看值传递和引用传递

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;
    }
}
结果如图所示:

分析如图所示:

总结

作为值参数(即值传递)时:传递的是栈中的数据。

作为引用参数(即引用传递时):传递的是栈本身的地址。





  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在C++,函数参数传递可以通过值传递(pass by value)和引用传递(pass by reference)两种方式进行。 值传递: - 值传递是指将实际参数的复制给形式参数,函数内部对形式参数的修改不会影响到实际参数。 - 在函数调用时,会创建形式参数的副本,函数对形式参数的操作只会影响到副本,并不会改变实际参数的。 - 值传递适用于简单的数据类型,如整型、浮点型、字符型等。 - 值传递的优点是简单、直观,并且不会改变原始数据。但对于大型结构体或对象,值传递会产生额外的内存开销。 引用传递: - 引用传递是指将实际参数的引用传递给形式参数,函数内部对形式参数的修改会影响到实际参数。 - 引用传递通过使用引用作为函数形参,可以直接访问和修改实际参数的。 - 引用传递适用于需要修改实际参数或传递大型结构体或对象的情况。 - 引用传递的优点是效率高,不会产生额外的内存开销,并且可以直接修改实际参数的。但需要注意引用传递可能会对原始数据造成意外的修改。 使用值传递还是引用传递应根据实际情况来决定。一般来说,对于基本数据类型和小型结构体可以使用值传递,而对于大型结构体或需要修改实际参数的情况,应使用引用传递。此外,也可以使用`const`修饰引用参数,以确保函数内部不会修改实际参数的

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值