1

考虑以下 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"]

然后代码按预期工作,但是原始代码中的任何一个版本都给了我这种意想不到的行为。看来 */initializer 意味着副本实际上是对字符串“x”的同一副本的引用。但是,如果我写的不是插入命令

a[0] = "a" + a[0]

然后我得到所需的输出。这是一个错误,还是有一些我不理解的功能在起作用?

4

2 回答 2

7

Array.new(size=0, obj=nil)的文档:

...它是使用obj的大小副本创建的(即,对同一obj的大小引用)。

数组 * int

...返回一个通过连接int副本构建的新数组self

因此,在您惊讶的两种形式中,您最终都会对同一个"x"对象进行三个引用,正如您所想的那样。我想说您可能会争论设计决策,但这是记录在案的故意行为,而不是错误。

我知道在不手动编写数组文字 ( ["x", "x", "x"]) 的情况下获得所需行为的最佳方法是

a = Array.new(3) {"x"}

或者当然,只有三个元素,这并不重要,但是如果有更大的元素,这种形式就派上用场了。

于 2012-07-17T06:31:31.900 回答
0

In short, although "x" is just a literal, it is an object. You use ["x'] * 3 so a is containing 3 same object. You insert 'a' to one of them, they will be all changed.

于 2012-07-17T06:42:34.743 回答