提问人:Cristian Diaconescu 提问时间:10/2/2008 最后编辑:Ry-Cristian Diaconescu 更新时间:5/16/2019 访问量:25160
Ruby 中的“通过引用传递参数”?
'pass parameter by reference' in Ruby?
问:
在 Ruby 中,是否可以通过引用传递具有值类型语义的参数(例如 Fixnum)? 我正在寻找类似于 C# 的“ref”关键字的东西。
例:
def func(x)
x += 1
end
a = 5
func(a) #this should be something like func(ref a)
puts a #should read '6'
顺便说一句。我知道我可以使用:
a = func(a)
答:
20赞
Christoph Schiessl
10/2/2008
#1
Ruby 根本不支持“通过引用传递”。一切都是一个对象,对这些对象的引用总是按值传递。实际上,在您的示例中,您正在按值传递对 Object 的引用副本。Fixnum
你的代码的问题在于,它不会修改传递的对象,而是创建一个全新的独立对象。x += 1
Fixnum
我认为,Java 程序员会称对象为不可变对象。Fixnum
评论
4赞
Damien Pollet
5/3/2009
当变量和参数只能包含对对象的引用时,我不明白 Ruby 不会通过 ref 传递的东西。说引用是按值传递的,这与说对象是按引用传递的是一样的。
2赞
newacct
4/24/2012
@Damien:不,不是。通过引用传递(例如在 C++、C#、PHP、Perl 中)允许您分配给变量,就像您在外部作用域中分配给它一样。您在这里尝试做的事情可以通过真正的引用传递来实现;但不能按引用值传递。
8赞
Damien Pollet
4/24/2012
你是对的,我正在再次阅读克里斯托夫的回答和我的评论,我不同意我 2009 年的自己。嗯。。。
32赞
jmah
10/2/2008
#2
可以通过显式传入当前绑定来实现此目的:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
评论
0赞
Cristian Diaconescu
4/3/2020
Ruby 绑定文档
0赞
Tim Baverstock
9/9/2020
这是一个可怕的骗局:涉及各种错别字、安全和丑陋风险。最好使用某种包装器,并将“绑定”留给“撬”之类的东西。
12赞
muesan
10/2/2008
#3
在 Ruby 中,你不能通过引用传递参数。对于您的示例,您必须返回新值并将其分配给变量 a,或者创建一个包含该值的新类并传递此类的实例。例:
class Container
attr_accessor :value
def initialize value
@value = value
end
end
def func(x)
x.value += 1
end
a = Container.new(5)
func(a)
puts a.value
8赞
Ivan Gusev
3/2/2015
#4
您可以尝试以下技巧:
def func(x)
x[0] += 1
end
a = [5]
func(a) #this should be something like func(ref a)
puts a[0] #should read '6'
评论
0赞
itarato
10/16/2017
从技术上讲,这也取代了写入时的变量(和列表中的引用)。
0赞
Tim Baverstock
9/9/2020
@itarato a 和 x 在其生存期内都指向同一个列表,因此没有任何东西可以替换任何变量,但列表的第一个条目会更改为指向不同的数字。我喜欢这个技巧,因为使用列表感觉比包装类 .get/.set 方法的心理开销要少,但这确实意味着您需要记住使用 [0] 取消引用它。
2赞
Sam Liao
3/2/2016
#5
http://ruby-doc.org/core-2.1.5/Fixnum.html
Fixnum 对象具有即时值。这意味着当它们被分配或 作为参数传递,则传递实际对象,而不是引用 那个对象。
此外,Ruby 是按值传递的。
-1赞
Ivan Cenov
5/16/2019
#6
但是,复合对象(如哈希)似乎是通过引用传递的:
fp = {}
def changeit(par)
par[:abc] = 'cde'
end
changeit(fp)
p fp
给
{:abc=>"cde"}
评论
0赞
Tim Baverstock
9/9/2020
哈希值按值传递,但值是对可变对象的引用。所以 fp 总是指向同一个哈希对象实例,但 changeit 会修改其内容。您可以通过打印fp.object_id和par.object_id来确认这一点。你不能仅仅通过给 par 分配一个不同的哈希来影响 fp 的值——这是“通过引用传递”所允许的。
评论