这段代码(在 Ruby 1.9 中)
word = 'atf'
new_word = word
word[0] = 'w'
puts new_word
给出响应“wtf”,这
word = 'ok'
new_word = word
word = 'wft'
puts new_word
给出了“好的”响应,这比我所期望的要多得多。这是 Ruby 中的一个错误,还是我错误地期望改变 word,但我改变它,不应该改变 new_word。
这段代码(在 Ruby 1.9 中)
word = 'atf'
new_word = word
word[0] = 'w'
puts new_word
给出响应“wtf”,这
word = 'ok'
new_word = word
word = 'wft'
puts new_word
给出了“好的”响应,这比我所期望的要多得多。这是 Ruby 中的一个错误,还是我错误地期望改变 word,但我改变它,不应该改变 new_word。
在第一个示例中,只有一个实际的字符串对象,并且您有两个引用它的变量名。因此,修改字符串会修改每个变量。你可以改为:
new_word = word.dup
制作副本。
word[0] = 'w'
word
是对变量引用的对象的方法调用。
word = 'wft'
是变量赋值。
正如其他答案中所说,您将变量指向同一个字符串对象。
''请记住'':Ruby 绝不会仅仅通过分配对象(或返回或传递给函数)来复制/复制对象。因此,如果您来自 C/C++,Ruby 仅适用于引用/指针。(如果您来自 Java:该行为与 Java 非原语非常相似)。
例如:
a = [1, 2]
b = a
b << 3
puts a.inspect
# prints [1, 2, 3]
如果您不习惯,甚至会更加困惑:
def foo(x)
x << 3
return nil
end
a = [1, 2]
foo(a)
foo(a)
puts a.inspect
# prints [1, 2, 3, 3]
在某些情况下,Ruby 提供了两种功能相同的方法,一种更改实际对象,另一种返回包含更改的新对象。
例如String#gsub(from, to)
返回一个包含这些更改的新字符串,另一方面 String#gsub!(from, to) changes the string itself. Another example would be
Array#reject vs.
Array#reject!`
Object#dup
复制一个对象(但不复制它的嵌套对象)。
请注意:在大多数情况下,不修改字符串被认为是好的样式
需要注意的重要一点是:
new_word = word
赋值不会复制into的值 。它设置使变量指向与变量相同的内存地址。word
new_word
new_word
word
因此,new_word[0] = 'x'
和将对变量和的值word[0] = 'x'
产生相同的影响。new_word
word
您可以通过以下任一方式解决问题:
new_word = word.dup
或者
new_word = word.clone
clone
并在内存中dup
创建变量值的副本,并返回对该内存的引用,然后将其分配给. 和之间存在差异,但它们超出了您的问题范围。new_word
clone
dup
此外,您会发现许多语言都以这种方式运行。例如,您可以在 C# 或 javascript 中尝试相同的语义,并看到相同的行为。