参考 - 参数 - 堆栈或堆

时间:2014-03-12 13:29:16

标签: c#

这只是一个理论问题,但我无法得到一个好的答案:

如果我通过ref传递参数,则传递对象本身而不是副本。

这让我感到困惑:据我所知,每个方法都有自己的堆栈帧 - 内存,它们不能离开。那么这是否意味着ref-Object被打包在堆上并且有一个对这个参数的引用,或者该方法是否进入调用方法的堆栈并在那里工作?

如果我的问题令人困惑,我很抱歉,我基本上想知道如何保存参考类型以及它有什么影响。

伊迪丝: 我想我没有说清楚。我理解价值和拒绝类型的概念。为了方便起见,我尝试用值类型来解释它,比方说Int:

过程1通过传递Int ByVal来调用Prodecure 2。这个int在Prodecure 2的堆栈上有自己的内存,这意味着,在P2中改变这个值不会改变P1中的值,因为这两个值在每个堆栈中保存一次。

现在与byref相同:Prodecure 2不会保存Int的副本,但可以直接访问此值。 (在我的Oppinion中)有两种可能性来完成这项工作:

  1. int被打包在堆上,实际上有2个指针 这个Int,但是从它现在的堆上,可以看到价值的变化 两个Prodecures。
  2. P2有类似的访问P1的堆栈 我想,是不可能的,因为这意味着, Stone中没有设置堆栈生命周期。
  3. 这是否更清楚我的意思?

3 个答案:

答案 0 :(得分:8)

传递的参数是某个对象的地址。该引用将与该方法的所有其他参数一起传递给堆栈。

在调用方法之前,实际对象本身就存在于它所居住的任何地方。那可能在堆栈中,它可能在堆中,没关系。通过引用传递对象的行为不会导致它在内存中移动,例如从堆栈移动到堆,或者从堆移动到堆栈。

答案 1 :(得分:1)

虽然Servy已经正确地回答了这个问题,但是对于将参数传递给ref和通过值传递对象的引用之间的区别,似乎存在很多混乱。出于这个原因,我认为值得提供一个简短的说明。

假设以下简单类:

class Player
{
    public Player(int health)
    {
        Health = health;
    }
    public int Health { get; set; }
}

我们现在可以测试更新对象的属性以及更改引用本身:

static void Main(string[] args)
{
    Player player = new Player(100);
    Console.WriteLine(player.Health);

    ChangeHealth(player);
    Console.WriteLine(player.Health);
    ChangeHealthByRef(ref player);
    Console.WriteLine(player.Health);

    ChangePlayer(player);
    Console.WriteLine(player.Health);
    ChangePlayerByRef(ref player);
    Console.WriteLine(player.Health);
}

static void ChangeHealth(Player player)
{
    player.Health = 80;
}

static void ChangeHealthByRef(ref Player player)
{
    player.Health = 60;
}

static void ChangePlayer(Player player)
{
    player = new Player(40);
}

static void ChangePlayerByRef(ref Player player)
{
    player = new Player(20);
}

输出:

100
80
60
60
20

ChangeHealth成功修改了Health对象的player属性。 ChangeHealthByRef也成功修改了Health对象的player属性。因此,尽管player使用了引用的副本,但在两次调用中,您都可以看到ChangeHealth引用的对象可以被修改。

现在,这是我认为人们感到困惑的部分:

ChangePlayer创建一个新的Player对象,用于修改中传递的引用的副本。这意味着更改不会反映在调用代码中(即Health仍然= 60)。 ChangePlayerByRef也会创建一个新的Player对象,但这一次,直接修改引用,这意味着 的更改会在调用代码中反映出来(即Health = 20)。

答案 2 :(得分:1)

看看这个问题的答案。

Do int ref parameter get boxed?

也许可以帮助您。

谢谢