Ruby中的字符串是否可变?

时间:2011-12-20 18:40:22

标签: ruby string immutability mutable

请考虑以下代码:

$ irb
> s = "asd"
> s.object_id   # prints 2171223360
> s[0] = ?z     # s is now "zsd"
> s.object_id   # prints 2171223360 (same as before)
> s += "hello"  # s is now "zsdhello"
> s.object_id   # prints 2171224560 (now it's different)

似乎可以在不创建新字符串的情况下更改单个字符。但是,附加到字符串显然会创建一个新字符串。

Ruby中的字符串是否可变?

6 个答案:

答案 0 :(得分:43)

是的,与Python不同,Ruby中的字符串是可变的。

s += "hello" "hello"附加到s - 创建一个全新的字符串对象。要附加到“就地”字符串,请使用<<,例如:

s = "hello"
s << "   world"
s # hello world

答案 1 :(得分:13)

ruby-1.9.3-p0 :026 > s="foo"
 => "foo" 
ruby-1.9.3-p0 :027 > s.object_id
 => 70120944881780 
ruby-1.9.3-p0 :028 > s<<"bar"
 => "foobar" 
ruby-1.9.3-p0 :029 > s.object_id
 => 70120944881780 
ruby-1.9.3-p0 :031 > s+="xxx"
 => "foobarxxx" 
ruby-1.9.3-p0 :032 > s.object_id
 => 70120961479860 

所以,字符串是可变的,但是+=运算符会创建一个新的字符串。 <<保持旧的

答案 2 :(得分:8)

Ruby String中的追加不是+=,而是<<

因此,如果您将+=更改为<<,您的问题就会自行解决

答案 3 :(得分:7)

Ruby中的字符串是可变的,但您可以通过冻结来更改它。

irb(main):001:0> s = "foo".freeze
=> "foo"
irb(main):002:0> s << "bar"
RuntimeError: can't modify frozen String

答案 4 :(得分:3)

Ruby Strings是可变的。但是你需要使用&lt;&lt;连接而不是+。
实际上串联字符串与
  +运算符(不可变)因为它会创建新的字符串对象  的&LT;&LT; operator(mutable)因为它在同一个对象中发生了变化。

答案 5 :(得分:0)

this pull request开始,我可以在Ruby 3.0中添加一个&#34;魔术评论&#34;这将使所有字符串不可变,而不是可变。

因为看起来你必须明确地添加这个评论,所以&#34;的答案似乎是字符串可变默认?&#34;仍然是肯定的,但有条件的是 - 取决于你是否在你的剧本中写了魔法评论。

修改

我被指向这个bug/issue on Ruby-Lang.org明确指出Ruby 3.0中的某些类型的字符串实际上默认是不可变的。