我看到object_id
字符串总是不同而符号'object_id
是相同的(如果值相等)。据我所知,符号和字符串之间的区别在于不变性和性能。我们不能只在变量中存储一个字符串并冻结它吗?
答案 0 :(得分:1)
[...]我们不能只将字符串存储在变量中并冻结它吗?
几乎,最新版本的Ruby可以优化冻结字符串:
'foo'.freeze.object_id #=> 70313275108080
'foo'.freeze.object_id #=> 70313275108080
但这种优化是有限的。它适用于字符串文字(如上所示),但如果字符串稍后被冻结则不起作用:
a = 'foo'
a.freeze
a.object_id #=> 70313275335500
b = 'foo'
b.freeze
b.object_id #=> 70313275274260
除非您启用frozen_string_literal
功能:
# frozen_string_literal: true
puts 'foo'.object_id
puts 'foo'.object_id
输出:
$ ruby test.rb
70185151269500
70185151269500
或者,从命令行:
$ ruby --enable-frozen-string-literal -e "puts 'foo'.object_id, 'foo'.object_id"
70102955495340
70102955495340
答案 1 :(得分:0)
freeze
阻止修改实际对象,但是变量是对对象的引用,因此您仍然可以更改引用。以下例如完全有效。
a = "foo"
a.freeze
a = "boo"
在a
结尾处等于“boo”。
在Ruby版本2.1及更早版本中,为符号分配了一个可用的object_id
,并且只要使用相同的符号标识符,就会始终使用相同的object_id;这绝不是垃圾收集。这是不可变的,但它也更有效(更少的内存开销)。
在Ruby 2.2及更高版本中,行为基本相同,除了符号可以被垃圾收集。这种变化的原因是为了防止符号DoS攻击。