Ruby noob here
我理解ruby确实通过函数参数的引用传递
然而,我感觉这与传统的c / c ++风格通过引用
略有不同示例代码:
def test1(str)
str += ' World!'
end
def test2(str)
str << ' World!'
end
str = 'Hello'
test1(str)
p str # Hello
test2(str)
p str # Hello World!
如果我在c / c ++中使用引用,我希望test1
也返回Hello World!
。
这只是出于好奇 - 任何解释都会受到赞赏
答案 0 :(得分:5)
我理解ruby确实通过函数参数的引用传递
Ruby始终是严格按值传递的。 Ruby中没有任何pass-by-reference。
这只是出于好奇 - 任何解释都会受到赞赏
为什么你的代码片段没有显示你期望传递引用的结果的简单解释是Ruby不是通过引用传递的。它是按值传递的,您的代码段证明了这一点。
这是一个小片段,它表明Ruby实际上是按值传递而不是通过引用传递:
#!/usr/bin/env ruby
def is_ruby_pass_by_value?(foo)
foo << <<~HERE
More precisely, it is call-by-object-sharing!
Call-by-object-sharing is a special case of pass-by-value,
where the value is always an immutable pointer to a (potentially mutable) value.
HERE
foo = 'No, Ruby is pass-by-reference.'
return
end
bar = ['Yes, of course, Ruby *is* pass-by-value!']
is_ruby_pass_by_value?(bar)
puts bar
# Yes, of course, Ruby *is* pass-by-value!,
# More precisely, it is call-by-object-sharing!
# Call-by-object-sharing is a special case of pass-by-value,
# where the value is always an immutable pointer to a (potentially mutable) value.
Ruby 确实允许对象变异,不是纯函数式语言,如Haskell或Clean。
答案 1 :(得分:1)
在第一种情况下,当您执行str += ' World!'
str = "Hello"
=> "Hello"
str.object_id
=> 69867706917360
str += " World"
=> "Hello World"
str.object_id
=> 69867706885680
str = "Hello"
=> "Hello"
str.object_id
=> 69867706856200
str << " World"
=> "Hello World"
str.object_id
=> 69867706856200
str = "Hello"
=> "Hello"
str.object_id
=> 69867706786780
str.freeze
=> "Hello"
str << " World"
RuntimeError: can't modify frozen String
str += " World"
=> "Hello World"
&#34;&LT;&LT;&#34;是二进制左移运算符。左操作数值向左移动右操作数指定的位数。
所以&#34;&lt;&lt;&#34;没有创建新字符串,str.contact("World")
也不会创建新字符串。
方法test1不必对返回的结果做任何事情,你可以试试这个方法:
def test1(str)
str.concat(' World!')
end
答案 2 :(得分:0)
查看以下对测试的调整,通过显示对象的object_id,您可以轻松查看它是否相同。由于+ =连接,Test1返回另一个String对象,但之后不再使用它。 这看起来像是通过引用传递,但实际上它是指向传递的对象的指针的值。我能找到的最好的explenation是here,作者称之为pass-reference-by-value
def test1(str)
p ["in test1 before", str.object_id]
str += ' World!'
p ["in test1 after", str.object_id]
str
end
def test2(str)
p ["in test2", str.object_id]
str << ' World!'
end
str = 'Hello'
p ["in main", str.object_id]
test1(str)
p str # Hello
p ["after test1", str.object_id]
test2(str)
p str
p ["after test2", str.object_id]
给出
["in main", 12363600]
["in test1 before", 12363600] # the same object, so pointer to object passed by value
["in test1 after", 12362976] # returns a new object, the old is unchanged
"Hello"
["after test1", 12363600] # idem
["in test2", 12363600]
"Hello World!"
["after test2", 12363600]
# still the same object
答案 3 :(得分:0)
引用了红宝石,除了数字true
,false
,nil
之类的值以外,还引用了其他内容。
a = "hello"
b = a
a.replace("Hola")
p a # Hola
p b # Hola
您想在开头添加魔术注释。
# frozen_string_literal: true
a = "hello"
b = a
a.replace("Hola") # can't modify frozen String: "hello" (FrozenError)
答案 4 :(得分:-2)
def test1(str)
str += ' World!'
end
operator +=
是ruby中的一个语法糖。表达式a += b
转换为a = a + b
。应用于+
实例的运算符String
创建新的String,它是两个参数的串联。这就是为什么在第一种情况下不修改str的原因。
另外,我想纠正你的陈述:
据我所知,ruby通过函数参数的引用传递
实际上,ruby通过引用传递除“值类型”之外的每个参数 - 即。值nil
,true
,false
和类Fixnum
的实例