考虑以下Ruby代码:
a = ["x"] * 3 # or a = Array.new(3, "x")
a[0].insert(0, "a")
a.each {|i| puts i}
我希望输出为ax,x,x(当然在新行上)。但是,使用Ruby 1.9.1,输出是ax,ax,ax。这是怎么回事?我已将问题缩小到定义数组a
的方式。如果我明确写出
a = ["x", "x", "x"]
然后代码按预期工作,但原始代码中的任何一个版本都给了我这种意想不到的行为。似乎* /初始化程序意味着副本实际上是对字符串“x”的同一副本的引用。但是,如果不是我写的插入命令
a[0] = "a" + a[0]
然后我得到了所需的输出。这是一个错误,还是在工作中有一些我不理解的功能?
答案 0 :(得分:7)
Array.new(size=0, obj=nil)的文档:
...它是使用大小 obj 的副本创建的(即 size 引用相同的 obj )。
...返回通过连接
self
的 int 副本构建的新数组
因此,在您惊讶的两种形式中,您最终会得到三个对同一"x"
对象的引用,就像您想到的那样。我会说你可能会争论设计决定,但这是一个有记录的故意行为,而不是一个错误。
我知道在不手动编写数组文字(["x", "x", "x"]
)的情况下获得所需行为的最佳方式是
a = Array.new(3) {"x"}
当然,只有三个元素,它没什么关系,但有了更大的东西,这个形式就派上用场了。
答案 1 :(得分:0)
简而言之,虽然“x”只是一个文字,但它是一个对象。您使用["x'] * 3
,因此a包含3个相同的对象。您将'a'插入其中一个,它们将全部更改。