在Ruby中更改字符串中的字符时出现意外行为

时间:2013-03-14 15:28:18

标签: ruby

此代码(在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

给出响应“ok”,这是我所期待的更多。这是Ruby中的一个错误,或者我错了,我希望改变它,但是我改变它,不应该改变new_word。

4 个答案:

答案 0 :(得分:3)

在第一个示例中,只有一个实际的字符串对象,并且您有两个引用它的变量名称。因此,修改字符串会修改每个变量。你可以这样做:

new_word = word.dup

制作副本。

答案 1 :(得分:1)

word[0] = 'w'是对word变量引用的对象的方法调用。

word = 'wft'是变量赋值。

答案 2 :(得分:1)

如在其他答案中所述,您将变量指向同一个字符串对象。

''请重新启动'':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,另一方面String#gsub!(from,to)changes the string itself. Another example would be Array#reject vs. Array#reject!`< / p>

Object#dup复制一个对象(但不是它的嵌套对象)。

请注意:在大多数情况下,不修改字符串被认为是好风格

答案 3 :(得分:0)

需要注意的重要事项是:

new_word = word

分配word值复制到new_word。它设置使变量new_word指向相同的内存地址作为变量word

因此,new_word[0] = 'x'word[0] = 'x'对> <{1}}和new_word具有相同的效果。

您可以通过执行以下操作来解决问题:

word

new_word = word.dup 

new_word = word.clone clone变量的内存中创建副本,并返回对该内存的引用,然后是分配给dupnew_wordclone之间存在差异,但这些差异超出了您的问题范围。

此外,您会发现许多语言都以这种方式运行。例如,您可以在C#或javascript中尝试相同的语义,并看到相同的行为。