2017-01-12 41 views
1

我很难看到为字符串对象的新实例创建值的过程与为字符串字面值创建值不同。Ruby中的String.new与字符串文字有什么区别?

a = String.new("Hello") 
# => "Hello" 

b = "Hello" 
# => "Hello" 

,如果我跑

a == b 
# => true 

同值!这是怎么回事?

+3

'海峡= “哦,我的”'是'String.new速记( “哦,我的”)'差不多。有关包含编码的差异,请参阅[String#new](http://ruby-doc.org/core-2.3.0/String.html#method-c-new)。通常,使用文字分配。 –

回答

1

==检查等内容。

equal?检查相同的身份。

a = "hello" 
b = "hello" 

a == b # => true 
a.equal?(b) # => false 

在Ruby中字符串字面量都不是一成不变的,从而创造一个字符串,并使用文字确实是相同的。在这两种情况下,Ruby在每次评估表达式时都会创建一个新的字符串实例。

这些都因此相同

10.times { String.new } 
# is the same as 
10.times { "" } 

让我们验证这一点

10.times { puts "".object_id } 

打印10不同的号码

70227981403600 
70227981403520 
70227981403460 
... 

为什么?字符串默认是可变的,因此每次在源代码中到达字符串文字时,Ruby都必须创建一个副本。即使这些文字在实践中通常很少修改。

因此,Ruby程序通常会创建过量的短期字符串对象,这会对垃圾回收造成巨大压力。 Rails应用程序创建500,000个短期字符串仅用于处理一个请求并不罕见,这是将Rails扩展到数百万甚至1亿用户的主要性能瓶颈之一。

为了解决Ruby 2.3引入的冻结字符串文字,其中所有字符串文字默认为不可变。由于这不是向后兼容它选择加入一个编译

# frozen_string_literal: true 

让我们验证这也

# frozen_string_literal: true 
10.times { puts "".object_id } 

打印相同数量的10倍

69898321746880 
69898321746880 
69898321746880 
... 

有趣的事实,在散列中设置密钥还会创建一个字符串的副本

str = "key" 
hash = {} 
hash[str] = true 
puts str.object_id 
puts hash.keys.first.object_id 

打印两个不同的号码

70243164028580 
70243132639660 
4

字符串文字是一个字符串对象。在早期版本的Ruby中没有区别。

从Ruby 2.3开始,您可以选择冻结字符串文字。它是用Ruby 3.0

计划的默认,这意味着...

x = "Hello" 
x.upcase! 

...会产生一个错误,因为字符串是不可变的。

使用构造...

x = String.new("Hello") 
x.upcase! 

工作正常。

1

在你的例子中,ab是c类引用而不是指针。所以你是比较值而不是对象。

1

相同的值!这是怎么回事?

没什么特别的情况,您可以创建无数个具有相同值的局部变量。

您可以使用Object#object_id看到,这些变量实际上不同的对象

a = String.new("Hello") 
b = "Hello" 
a.object_id #=> 70295696460580 
b.object_id #=> 70295696294220 
相关问题