1

在 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

如果你能提供你的答案的证据,那就太好了:)。

4

3 回答 3

1
"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文字字符串将引用内部化版本。
于 2015-10-05T19:41:37.857 回答
1

不幸的是,这真的很难说。YARV 2.1+确实执行了一些字符串实习优化,但是,不清楚这些优化是 YARV 2.1+ 的私有内部实现细节还是 Ruby 2.1+ 语义的官方保证特性,即 Ruby 2.1+ 语言规范的一部分。问题是:在matz 的头脑之外没有“Ruby 2.1+ 语言规范”,所以无处可查

它们在 YARV 2.1 的 ChangeLog 中进行了描述,但同样,这并没有说明什么:ChangeLog 将 YARV 的功能与 Ruby 的功能自由地混合在一起,而没有指明哪个是哪个。

于 2015-10-06T01:37:26.583 回答
1

在 Ruby 2.1 中,编译器对 "str".freeze 进行了优化,以在每次调用时返回一个共享的冻结字符串。

来自:http ://tmm1.net/ruby21-fstrings/

您可以使用该object_id方法自己进行测试。

"foo".freeze.object_id
=> 87323600

foo = "foo".freeze
foo.object_id
=> 87323600
于 2015-10-05T19:39:45.827 回答