1

このコード (Ruby 1.9)

word = 'atf'
new_word = word
word[0] = 'w'
puts new_word 

応答「wtf」を返します。これは

word = 'ok'
new_word = word
word = 'wft'
puts new_word

私が期待するよりもはるかに多くの「OK」という応答を返します。これは Ruby のバグですか、それとも word を変更しても new_word は変更されないという期待が間違っているのでしょうか。

4

4 に答える 4

3

最初の例では、実際の文字列オブジェクトは 1 つだけで、それを参照する変数名が 2 つあります。したがって、文字列を変更すると、各変数が変更されます。代わりに次のことができます。

new_word = word.dup

コピーを作成します。

于 2013-03-14T15:31:31.047 に答える
1

word[0] = 'w'word変数によって参照されるオブジェクトに対するメソッド呼び出しです。

word = 'wft'変数の代入です。

于 2013-03-14T15:32:52.273 に答える
1

他の回答で述べたように、同じ文字列オブジェクトへの変数を指しています。

''覚えておいてください'': Ruby は、オブジェクトを代入 (または関数に返すか渡す) するだけではコピー/複製しません。したがって、C/C++ から来た場合、Ruby は参照/ポインターのみで動作します。(そして、Java から来た場合: 動作は Java の非プリミティブと非常に似ています)。

例えば:

a = [1, 2]
b = a
b << 3
puts a.inspect
# prints [1, 2, 3]

慣れていない場合はさらに混乱します。

def foo(x)
  x << 3 
  return nil
end

a = [1, 2]
foo(a)
foo(a)
puts a.inspect
# prints [1, 2, 3, 3]

場合によっては、Ruby は同じ機能の 2 つのメソッドを提供します。1 つは実際のオブジェクトを変更し、もう 1 つは変更を含む新しいオブジェクトを返します。

たとえばString#gsub(from, to)、これらの変更を含む新しい文字列を返しますが、一方で String#gsub!(from, to) changes the string itself. Another example would beArray#reject vs.Array#reject!`

Object#dupオブジェクトをコピーします (ただし、そのネスト オブジェクトはコピーしません)。

注意: ほとんどの場合、文字列を変更しないことは適切なスタイルと見なされます

于 2013-03-14T15:44:01.380 に答える
0

注意すべき重要なことは、次の意味です。

new_word = word

代入はの値をにコピーしませ変数が変数と同じメモリアドレスを指すように設定します。 wordnew_wordnew_wordword

したがって、new_word[0] = 'x'とは変数との両方の値にword[0] = 'x'同じ影響を与えます。new_wordword

次のいずれかを実行して問題を解決できます。

new_word = word.dup 

また

new_word = word.clone

clone変数の値のメモリ内にコピーdup作成し、そのメモリへの参照を返します。これは に割り当てられます。と の間には違いがありますが、それらはあなたの質問の範囲を超えています。new_wordclonedup

さらに、多くの言語がこのように機能していることがわかります。たとえば、C# または JavaScript で同じセマンティクスを試して、同じ動作を確認できます。

于 2013-03-14T15:42:51.673 に答える