Ruby:数组通过引用传递给函数? [复制]

Posted

技术标签:

【中文标题】Ruby:数组通过引用传递给函数? [复制]【英文标题】:Ruby: array is being passed by reference into function? [duplicate] 【发布时间】:2017-06-02 20:56:39 【问题描述】:

下面有一个简单的代码

    def testarray
      arr_tree = [1,2,3,4,5]
      (1..3).each do |index|
        abcde(arr_tree)
        puts arr_tree[0]
      end
    end

    def abcde(node_tree)
      node_tree[0] += 100
    end

所以在 testarray 函数中,我有一个数组 arr_tree,它被传递给函数 abcde。我在abcde 函数中更改数组的值并在testarray 中打印数组,我在这里得到了更改后的值。所以输出是

101
201
301

但我期待

1
1
1

请解释为什么结果是这样的?还有我怎样才能达到我的预期效果?

【问题讨论】:

【参考方案1】:

你的假设是错误的:ruby 不是 pass-by-reference,它始终是pass-by-value。您可以通过运行这个简单的测试轻松地验证这一点:

def foo(bar)
  bar = 'reference'
end

baz = 'value'

foo(baz)

puts "Ruby is pass-by-#baz"
# Ruby is pass-by-value

更准确地说,Ruby 是call-by-object-sharing(也称为call-by-objectcall-by-sharing),是的一个特例>按值传递,其中传递的始终是指向(可能)共享(可能)可变对象的指针:

def is_ruby_pass_by_value?(foo)
  foo.replace('More precisely, it is call-by-object-sharing!')
  foo = 'No, Ruby is pass-by-reference.'
end

bar = 'Yes, of course, Ruby *is* pass-by-value!'

is_ruby_pass_by_value?(bar)

p bar
# 'More precisely, it is call-by-object-sharing!'

但是,这实际上与您的问题无关。它与 pass-by-referencepass-by-value 无关。

所以在 testarray 函数中,我有一个数组 arr_tree,它被传递给函数 abcde。我在abcde 函数中更改数组的值并在testarray 中打印数组我在这里得到更改后的值。

你得到改变的价值是因为你改变了价值。就这么简单。 Ruby 不是纯函数式编程语言,它确实具有可变状态。如果你改变那个状态,那么旧的状态就消失了,只有新的状态存在。

你自己写的:

我改变了数组的值

好吧,如果你改变数组,数组就会改变!整个代码中只有一个数组。

请解释一下为什么会出现这样的结果?

数组改变是因为你改变了数组。

还有我怎样才能达到我的预期效果?

你可以通过不改变数组来实现你的结果:

def testarray
  arr_tree = [1, 2, 3, 4, 5]
  (1..3).each do |index|
    abcde(arr_tree)
    puts arr_tree[0]
  end
end

def abcde(node_tree)
  [node_tree.first + 100, *node_tree.drop(1)]
end

【讨论】:

【参考方案2】:

在 Ruby 中,一切都“作为对象传递”。

数组是对象。

如果你想避免副作用,请复制参数

def abcde(node_tree)
  copy = node_tree.dup
  copy[0] += 100
  copy
end

请注意,由于您将变量命名为 tree,因此 dup 方法仅生成浅拷贝。浅意味着复制数组而不是复制其元素。

为什么我上面没有说“通过引用传递”?

“通过引用传递”是另一种语言的概念,在 Ruby 的上下文中没有意义。从技术上讲,Ruby 的本机实现使用按值传递,其中值是指向对象结构的指针。然而,将 Ruby 视为使用“按值传递”是一种误导,因为它不会在将数据结构传递给函数之前创建数据结构的副本。这似乎是你认为会发生的事情……

【讨论】:

“按引用传递”意味着为变量分配另一个值也会改变调用者范围内的变量,例如node_tree = []。这是 Ruby 不允许的。 对不起,这是错误的。 Ruby 不是通过引用传递的。 当您在 Ruby 中说“通过引用传递”时,意味着您尝试将 C++ 概念应用于错误的语言。 通过引用传递仍然是错误的,即使是引号。 点了,你们俩,更新了。

以上是关于Ruby:数组通过引用传递给函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

PHP 中的数组是作为值复制还是作为对新变量的引用,以及何时传递给函数?

对象作为参数传递给另一个类,通过值还是引用?

JS中函数参数值传递和引用传递

通过引用传递或通过复制传递 - Ruby 模块 [重复]

为啥在通过 const 引用传递临时值时调用复制构造函数?

通过引用将字符串数组传递给 C 函数