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のsizeコピー(つまり、同じobjへのsize参照) で作成されます。

およびArray * int :

... のintコピーを連結して構築された新しい配列を返しますself

したがって、驚くべきことに、両方の形式で、同じ"x"オブジェクトへの 3 つの参照が作成されることになります。設計上の決定について議論するかもしれませんが、それは文書化された意図的な動作であり、バグではありません。

["x", "x", "x"]配列リテラル ( )を手動で記述せずに、必要な動作を得るために私が知っている最善の方法は、

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

もちろん、要素が 3 つだけの場合はそれほど問題ではありませんが、より大きな要素がある場合は、この形式が便利です。

于 2012-07-17T06:31:31.900 に答える
0

つまり、「x」は単なるリテラルですが、オブジェクトです。["x'] * 33つの同じオブジェクトが含まれているように使用します。それらの 1 つに 'a' を挿入すると、すべてが変更されます。

于 2012-07-17T06:42:34.743 に答える