对象分配和指针

jer*_*son 6 ruby copy object variable-assignment

我对Ruby中的对象赋值和指针感到有点困惑,并编写了这个代码片段来测试我的假设.

class Foo
    attr_accessor :one, :two
    def initialize(one, two)
        @one = one
        @two = two
    end

end

bar = Foo.new(1, 2)
beans = bar

puts bar
puts beans

beans.one = 2
puts bar
puts beans
puts beans.one
puts bar.one
Run Code Online (Sandbox Code Playgroud)

我曾经假设当我将bar分配给bean时,它会创建一个对象的副本,而修改一个不会影响另一个.唉,输出显示不然.

^_^[jergason:~]$ ruby test.rb 
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
2
2
Run Code Online (Sandbox Code Playgroud)

我相信这些数字与对象的地址有关,并且对于bean和bar都是相同的,当我修改bean时,bar也会被改变,这不是我所期望的.看来我只是创建一个指向对象的指针,而不是它的副本.在分配时复制对象而不是创建指针需要做什么?

使用Array类进行的测试也显示了一些奇怪的行为.

foo = [0, 1, 2, 3, 4, 5]
baz = foo
puts "foo is #{foo}"
puts "baz is #{baz}"
foo.pop
puts "foo is #{foo}"
puts "baz is #{baz}"

foo += ["a hill of beans is a wonderful thing"]
puts "foo is #{foo}"
puts "baz is #{baz}"
Run Code Online (Sandbox Code Playgroud)

这会产生以下不稳定的输出:

foo is 012345
baz is 012345
foo is 01234
baz is 01234
foo is 01234a hill of beans is a wonderful thing
baz is 01234
Run Code Online (Sandbox Code Playgroud)

这让我大吃一惊.在foo上调用pop会影响baz,因此它不是副本,但是将某些内容连接到foo上只会影响foo,而不会影响baz.那么我什么时候处理原始对象,何时处理副本?在我自己的课程中,我如何确保分配副本,而不是指针?帮助这个迷茫的家伙.

mck*_*eed 11

这个问题有很多问题.要知道的主要事情是赋值永远不会在ruby中复制,但方法通常返回新对象而不是修改现有对象.对于像Fixnums这样的不可变对象,你可以忽略它,但对于像数组或Foo实例这样的对象,你必须做一个副本bar.dup.

至于数组示例,foo +=没有连接到存储在的数组上foo,为此你会这样做foo.concat(['a']).相反,它正在制作一个新阵列并分配foo给它.Array类的文档提到了哪些方法在适当的位置改变了数组并返回了一个新数组.

  • 在Foo中实现clone只会返回`Foo.new(self.one,self.two)` (2认同)