“参考”的使用方式是不是有歧义?

Posted

技术标签:

【中文标题】“参考”的使用方式是不是有歧义?【英文标题】:Is there ambiguity in the way "reference" is used?“参考”的使用方式是否有歧义? 【发布时间】:2011-06-12 03:11:21 【问题描述】:

例如,在 php 中我们可以这样写:

class C 
    var $x;

    function __construct($x) 
        $this->x = $x;
    

    function __toString() 
        return (string)$this->x;
    


function f1($obj) 
    $obj->x = 2;


$a = new C(1);
f1($a);
echo $a; // 2

有些人会说这表明对象是通过引用传递的,因为您可以修改它们的属性,并且这些更改会反映在类之外。即,对象不会像原语那样被复制。

但是我们可以这样写:

function f2($obj) 
    $obj = new C(2);



$b = new C(1);
f2($b);
echo $b; // 1

这表明对象根本不是通过引用传递的。实际上,对象被复制(即,按值传递)但不是deep-复制的; $obj 被复制了,但 $x 仍然指的是同一个东西。

我听说“参考”这个词过去有两种意思;有人会说 PHP 是按引用传递,也有人会说是按值传递。

如果我们说 PHP 是通过引用传递的,那么定义一个类似的函数是什么意思

function f3(&$obj)

那个函数引用一个对象,这表明第一个意思是错误的。

但是对于像 C++ 这样的语言和 C# 中的结构呢?我的 C++ 有点生疏,但我相信整个类在传递它时实际上会被深度复制,这就是为什么鼓励你的函数尽可能使用引用或使用指针的原因。在 C# 中,结构和类的传递方式有所不同。

如果不是按值传递,你怎么称呼这种深度复制行为?

似乎我们有 3 种行为,只有两个短语来描述它们,这在社区中造成了很多混乱。

哎呀,我只是在等你们中的一个告诉我我在这里写错了。


总的来说,这三种行为是:

    对象被深度复制(对象及其属性被克隆) 仅复制对象(其属性仍引用同一块内存) 对象根本没有被复制

从技术上讲,我们应该如何称呼这些行为?路过-???

【问题讨论】:

有一天(或者可能不会),PHP 将为参数实现 const 关键字,这将消除任何歧义... :) 【参考方案1】:

您必须区分两件事……对变量的引用和对对象的引用。只要您不为参数 $obj 分配其他值,您就可以处理与函数外部完全相同的对象。在为它分配另一个对象后,变量发生了变化,但是由于您只传递了对该对象的引用而不是变量的引用,因此外部的变量仍然没有被触及,指向您的原始对象......

【讨论】:

【参考方案2】:

如果我有我的 druthers,.net 中的“对象引用”一词将被“object-id”之类的东西取代,以明确在大多数情况下,当一个对象被传递给例程时,object-id按值传递(尽管在某些情况下,例如 Dictionary.TryGetValue,其中 object-id 通过引用传递)。使用相同的术语来描述 object-id 和参数传递的类型会导致混淆。

【讨论】:

【参考方案3】:

在 C++ 中,前两个都称为按值传递。深度复制的深度取决于所讨论类的复制语义,程序员可以并且应该指定它(一些类是资源句柄,必须是浅复制的;其他类,例如大多数容器,必须是深复制的) -复制)。 Python 具有用于深复制和浅复制的库函数。深度复制有时被称为克隆,尤其是。在 C++ 和 Java 中。

第三种称为按引用传递。这是传递可以由被调用者就地修改的东西的通用术语。

(C 是这个约定的一个例外,因为它没有引用的概念,但指针传递与引用传递几乎相同。)

【讨论】:

【参考方案4】:

第一件事:您可能想阅读References Explained


通常,变量总是按值传递。重要的是实际价值。

如果变量“持有一个对象”,则它持有一个对该对象的引用

因此,当您有类似的函数定义时

function foo($bar) 

对象的引用被传递。这就是您可以更改对象的原因。

但是如果你给函数内部的变量分配一个新值,那么你只是用别的东西覆盖了引用,你失去了对对象的引用。

因此,假设您有一个变量 $someVar 传递给函数,$bar$someVar 将具有相同的值(即引用),但它们在内存中有自己的位置。

之前:

$someVar -> object_reference  ┐

                              ├ -> object

$bar     -> object_reference  ┘

之后:

$someVar -> object_reference  -> object



$bar     -> other_value

现在,如果函数定义是这样的

function foo(&$bar) 

那么你实际上被传递了一个对内存中某个其他变量的位置的引用

如果您使用foo($someVar) 调用该函数,$bar 将指向与$someVar 相同的位置,即如果您分配一个新值,您将覆盖内存中的该特定位置。

之前:

$someVar  ┐

          ├ ->  object_reference -> object

$bar      ┘

之后:

$someVar  ┐

          ├ ->  other_value         object

$bar      ┘

【讨论】:

那么......然后回答这个问题。你说,什么?对象是通过对对象的引用 传递的,而在另一种情况下,您是通过对内存中位置的引用?那么原始人呢?还是深度复制的对象?您在两种情况下都使用了“参考”一词,因此您同意,除非完全限定,否则存在歧义? @Mark:Imo 这个词没有歧义。在这两种情况下使用该术语是正确的,因为它们描述了相同的概念。如果参数未使用& 符号定义,您永远不会说函数接受引用。你知道,如果你传递对象,你可以修改它们的属性。请注意,在第二个示例中,您没有对传递的对象的属性进行操作,而是为变量分配了一个新值。引用只是唯一定义其他事物的事物。您会在其他 OO 语言中发现相同的行为。 @Mark:对不起,如果我不能以更容易理解的方式解释它。 不,我想我明白你的意思。在这个意义上,“参考”一直被使用,但是“通过参考传递”这个短语不是。这可能意味着......哦,算了吧。我了解幕后发生的事情,这只是愚蠢的措辞。我认为我们应该将 & 号的情况称为“别名”。

以上是关于“参考”的使用方式是不是有歧义?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决情感分析中的歧义?

如何理解分词术的歧义

Android:消除文件路径的歧义

使用 laravel 范围避免歧义

fortran调用 带有参数 且 返回类型为数组的函数 及 相关歧义分析

fortran调用 带有参数 且 返回类型为数组的函数 及 相关歧义分析