通过引用与值传递对象
Posted
技术标签:
【中文标题】通过引用与值传递对象【英文标题】:Passing objects by reference vs value 【发布时间】:2013-06-27 12:31:42 【问题描述】:我只是想检查一下我对 C# 处理事物方式的理解,然后再深入研究我的类的设计。我目前的理解是:
Struct
是一个 value 类型,这意味着它实际上包含其中定义的数据成员。
Class
是一个 reference 类型,这意味着它包含对其中定义的数据成员的引用。
方法签名通过值传递参数,这意味着将值的副本传递到方法内部,这对于大型数组和数据结构来说成本很高。
使用 ref 或 out 关键字定义参数的方法签名将改为通过 reference 传递参数,这意味着指向而是提供对象。我不明白当我调用一个方法时会发生什么,实际发生了什么。 new() 是否被调用?它只是自动复制数据吗?还是它实际上只是指向原始对象?以及使用 ref 和 out 对此有何影响?
【问题讨论】:
您是在问值类型或引用类型会发生什么? 两者,我想。但 Avi 下面的回答似乎涵盖了这两种情况。 【参考方案1】:将值类型变量传递给方法意味着将变量的副本传递给方法。方法内部对参数的任何更改都不会影响存储在变量中的原始数据。
如果你想让被调用的方法改变参数的值,你必须通过引用传递它,使用 ref 或 out 关键字。
当你通过值传递引用类型的参数时,可以改变引用指向的数据,例如类成员的值。但是,您不能更改引用本身的值;也就是说,您不能使用相同的引用来为新类分配内存并让它在块之外持续存在。为此,请使用 ref(或 out)关键字传递参数。
参考:Passing Parameters(C#)
【讨论】:
【参考方案2】:我不明白当我调用一个方法时会发生什么,实际发生了什么。 new() 是否被调用?它只是自动复制数据吗?还是它实际上只是指向原始对象?使用 ref 和 out 对此有何影响?
简短的回答:
空的构造函数不会被自动调用,它实际上只是指向原始对象。 使用 ref 和 out 不会影响这一点。
长答案:
我认为理解 C# 如何处理将参数传递给函数会更容易。 实际上,一切都在按价值传递真的吗?!一切都按价值计算? 是的!一切!
当然,传递类和简单类型的对象(例如 Integer)之间必须存在某种差异,否则,在性能方面将是一个巨大的倒退。
问题是,当你将对象的类实例传递给函数时,真正传递给函数的是指向类的指针。当然,指针可以按值传递而不会导致性能问题。
其实一切都是按值传递的;只是当 您正在“传递一个对象”,实际上是在传递对该对象的引用 对象(并且您正在按值传递该引用)。
一旦我们进入函数,给定参数指针,我们就可以关联到通过引用传递的对象。 您实际上不需要为此做任何事情,您可以直接与作为参数传递的实例相关联(如前所述,整个过程是在幕后完成的)。
了解了这里,你大概明白了,空的构造函数不会被自动调用,它其实只是指向原来的对象。
已编辑:
关于 out 和 ref,它们允许函数更改参数的值,并使该更改在函数范围之外持续存在。 简而言之,对值类型使用 ref 关键字的作用如下:
int i = 42;
foo(ref i);
将在 c++ 中翻译为:
int i = 42;
int* ptrI = &i;
foo(ptrI)
而省略 ref 将简单地转换为:
int i = 42;
foo(i)
为引用类型对象使用这些关键字,将允许您为传递的参数重新分配内存,并使重新分配在函数范围之外持续存在(有关更多详细信息,请参阅@ 987654321@)
旁注: ref 和 out 的区别在于 out 确保被调用的函数必须为 out 参数赋值,而 ref 没有这个限制,然后你应该通过自己分配一些默认值来处理它,因此, ref 意味着参数的初始值对函数很重要,可能会影响其行为。
【讨论】:
您对 ref/out 的解释不正确。首先,甚至不需要在值类型上使用它们,其次,它与按值传递引用的语义不同。按值传递引用和按引用传递值实际上是不同的(逻辑上和功能上),这篇文章表明对这里的核心概念缺乏理解。 @servy 你是对的,我专注于一棵树并错过了森林,我想我不太关注它,因为它不是主要问题,并举例说明了我的主要用途没有/参考...我已经更新了我的答案。你觉得现在够了吗? —— 并非如此。你的解释并没有真正解释太多。如果 OP 还不了解 C++,则该示例无济于事,并且重新分配引用类型的能力是您可以做的一件事,但它不能解释通过引用传递 的含义 i>. @AviTurner 你对 ref 的理解是有缺陷的。当您在参数上使用 ref 修饰符时,C# 会通过引用正确传递。 @AviTurner 是的,我也是这么理解的。那么,这不叫引用传递吗?由于使用 ref 参数,它隐式添加了另一层间接性并将指针传递给指针。我知道在一天结束时,正在传递一个值,但是由于它作为指向隐式传递的指针的指针,所以这个概念不是称为“通过引用传递”。如果不是这样,那什么叫引用传递?【参考方案3】:可悲的是,在 C# 或 VB.NET 中无法按值传递对象。例如,我建议您传递 New Class1(Object1),其中 Object1 是 Class1 的一个实例。您必须编写自己的 New 方法来执行此操作,但至少您可以轻松地为 Class1 传递值。
【讨论】:
以上是关于通过引用与值传递对象的主要内容,如果未能解决你的问题,请参考以下文章