【问题标题】:Symbols (storing strings in variables vs symbols)符号(将字符串存储在变量和符号中)
【发布时间】:2016-08-27 06:13:27
【问题描述】:

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

【问题讨论】:

    标签: ruby string symbols


    【解决方案1】:

    freeze 防止修改实际对象,但是变量是对对象的引用,因此您仍然可以更改引用。下面的例子是完全有效的。

    a = "foo"
    a.freeze
    a = "boo"
    

    在这个a的末尾等于“boo”。

    在 Ruby 2.1 及更早的版本中,为符号分配了可用的object_id,并且任何时候使用相同的符号标识符,都将始终使用相同的 object_id;这永远不会被垃圾收集。这是不可变的,但效率更高(内存开销更少)。

    在 Ruby 2.2 及更高版本中,行为基本相同,除了符号可以被垃圾收集。进行此更改的原因是为了防止符号 DoS 攻击。

    【讨论】:

    • 那么在哪里使用字符串以及在哪里使用符号呢?
    • 感谢您的回答!我将阅读有关符号 DoS 攻击的信息:)
    【解决方案2】:

    [...] 我们不能在变量中存储一个字符串并冻结它吗?

    几乎,最新版本的 Ruby 可以优化冻结字符串:

    'foo'.freeze.object_id #=> 70313275108080
    'foo'.freeze.object_id #=> 70313275108080
    

    但是这种优化是有限的。它适用于字符串 literals(如上所示),但如果字符串稍后被冻结则不起作用:

    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
    

    【讨论】:

    • 那么在哪里使用字符串以及在哪里使用符号呢?
    • @RamziddinMakhmudov 如果其内容很重要,即字符,则使用字符串。如果需要标识符或标签,请使用符号。
    • 感谢您清晰易懂的回答 =)
    • 顺便说一句,冻结字符串优化是对字符串的优化。它并不是为了替代符号。
    • 感谢您的帮助,斯特凡!我很感激:)
    猜你喜欢
    • 2017-06-06
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 2017-11-24
    • 2012-09-07
    • 2020-08-09
    • 1970-01-01
    相关资源
    最近更新 更多