在 ruby 2.2 中,以下是否分配新的 String 对象或使用已被实习的对象?假设这些命令按照给定的顺序运行。
"foo".freeze
foo = "foo".freeze
foo2 = "foo"
foo2.freeze
foo3 = foo.freeze
foo4 = ["foo".freeze].first
foo5 = ["foo"].map(&:freeze).first
如果你能提供你的答案的证据,那就太好了:)。
在 ruby 2.2 中,以下是否分配新的 String 对象或使用已被实习的对象?假设这些命令按照给定的顺序运行。
"foo".freeze
foo = "foo".freeze
foo2 = "foo"
foo2.freeze
foo3 = foo.freeze
foo4 = ["foo".freeze].first
foo5 = ["foo"].map(&:freeze).first
如果你能提供你的答案的证据,那就太好了:)。
"foo".freeze.object_id # => 70148079771220
foo = "foo".freeze
foo.object_id # => 70148079771220
foo2 = "foo"
foo2.object_id # => 70148076813240
foo2.freeze
foo2.object_id # => 70148076813240
foo3 = foo.freeze
foo3.object_id # => 70148079771220
foo4 = ["foo".freeze].first
foo4.object_id # => 70148079771220
foo5 = ["foo"].map(&:freeze).first
foo5.object_id # => 70148079700740
所以基本上,你可以通过两条规则来合理化它:
String#freeze
不会更改已引用字符串的对象 ID。String#freeze
文字字符串将引用内部化版本。不幸的是,这真的很难说。YARV 2.1+确实执行了一些字符串实习优化,但是,不清楚这些优化是 YARV 2.1+ 的私有内部实现细节还是 Ruby 2.1+ 语义的官方保证特性,即 Ruby 2.1+ 语言规范的一部分。问题是:在matz 的头脑之外没有“Ruby 2.1+ 语言规范”,所以无处可查。
它们在 YARV 2.1 的 ChangeLog 中进行了描述,但同样,这并没有说明什么:ChangeLog 将 YARV 的功能与 Ruby 的功能自由地混合在一起,而没有指明哪个是哪个。
在 Ruby 2.1 中,编译器对 "str".freeze 进行了优化,以在每次调用时返回一个共享的冻结字符串。
来自:http ://tmm1.net/ruby21-fstrings/
您可以使用该object_id
方法自己进行测试。
"foo".freeze.object_id
=> 87323600
foo = "foo".freeze
foo.object_id
=> 87323600