Ruby 字符串按引用函数参数传递
Ruby string pass by reference function parameter
Ruby 菜鸟在这里
我了解 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
也 return Hello World!
。
这只是出于好奇 -- 任何解释将不胜感激
def test1(str)
str += ' World!'
end
运算符+=
是ruby中的语法糖。表达式 a += b
转换为 a = a + b
。应用于 String
实例的运算符 +
创建新的字符串,它是两个参数的串联。这就是为什么在第一种情况下不修改 str 的原因。
另外我想纠正你的说法:
我理解 ruby 确实通过引用传递函数参数
实际上 ruby 通过引用传递每个参数,除了 "value types" - 即。值 nil
、true
、false
和 class Fixnum
的实例
看看你的测试的以下改编,通过显示你的对象的 object_id 你可以很容易地看出它是否相同。 Test1 returns 另一个 String 对象,因为 += 连接但之后没有使用。
这看起来像是通过引用传递,但实际上传递的是指向对象的指针的值。我能找到的最好的解释是 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
在第一种情况下,您创建了一个新对象 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"
"<<" is a Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.
因此“<<”不会创建新字符串,str.contact("World")
也不会创建新字符串。
方法test1不需要对返回结果做任何处理,你可以试试这个方法:
def test1(str)
str.concat(' World!')
end
I understand ruby does pass by reference for function parameters
Ruby 始终严格按值传递。 Ruby 中没有传递引用。
This is simply out of curiosity -- any explanations would be appreciated
为什么您的代码片段没有显示您期望的传递引用结果的简单解释是 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这样的纯函数式语言或清洁。
STRING 被引用,在 ruby 中除了像数字 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)
Ruby 菜鸟在这里
我了解 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
也 return Hello World!
。
这只是出于好奇 -- 任何解释将不胜感激
def test1(str)
str += ' World!'
end
运算符+=
是ruby中的语法糖。表达式 a += b
转换为 a = a + b
。应用于 String
实例的运算符 +
创建新的字符串,它是两个参数的串联。这就是为什么在第一种情况下不修改 str 的原因。
另外我想纠正你的说法:
我理解 ruby 确实通过引用传递函数参数
实际上 ruby 通过引用传递每个参数,除了 "value types" - 即。值 nil
、true
、false
和 class Fixnum
看看你的测试的以下改编,通过显示你的对象的 object_id 你可以很容易地看出它是否相同。 Test1 returns 另一个 String 对象,因为 += 连接但之后没有使用。 这看起来像是通过引用传递,但实际上传递的是指向对象的指针的值。我能找到的最好的解释是 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
在第一种情况下,您创建了一个新对象 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"
"<<" is a Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.
因此“<<”不会创建新字符串,str.contact("World")
也不会创建新字符串。
方法test1不需要对返回结果做任何处理,你可以试试这个方法:
def test1(str)
str.concat(' World!')
end
I understand ruby does pass by reference for function parameters
Ruby 始终严格按值传递。 Ruby 中没有传递引用。
This is simply out of curiosity -- any explanations would be appreciated
为什么您的代码片段没有显示您期望的传递引用结果的简单解释是 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这样的纯函数式语言或清洁。
STRING 被引用,在 ruby 中除了像数字 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)