符号(在变量与符号中存储字符串)

时间:2016-05-02 13:02:56

标签: ruby string symbols

我看到object_id字符串总是不同而符号'object_id是相同的(如果值相等)。据我所知,符号和字符串之间的区别在于不变性和性能。我们不能只在变量中存储一个字符串并冻结它吗?

2 个答案:

答案 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攻击。