对象分配和指针 [英] Object assignment and pointers

查看:154
本文介绍了对象分配和指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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

我假设当我为bar指定bar时,会创建一个对象的副本,修改一个对象不会影响其他对象。唉,输出显示其他。

  ^ _ ^ [jergason:〜] $ ruby​​ test.rb 
# ; Foo:0x100155c60>
#< Foo:0x100155c60>
#< Foo:0x100155c60>
#< Foo:0x100155c60>
2
2

我相信这些数字与对象的地址,它们对于bean和bar都是相同的,当我修改bean时,bar也会更改,这不是我预期的。看来,我只创建一个指向该对象的指针,而不是它的副本。



使用Array类测试也显示了一些奇怪的行为,我需要做的是在赋值时复制对象,而不是创建一个指针。

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

foo + = [豆子山是一个奇妙的事]
putsfoo is#{foo}
putsbaz is# {baz}

这将产生以下wonky输出:



<$ c $ p> foo is 012345
baz is 012345
foo is 01234
baz is 01234
foo is 01234a hill of beans is a美妙的事情
baz is 01234

这打击了我的心。调用boo上的foo也会影响baz,所以它不是一个副本,但将foo连接到foo只影响foo,而不是baz。所以,当我处理原始的对象,我什么时候处理一个副本?在我自己的类中,我如何确保分配副本,并且不指针?帮助这个困惑的家伙。

解决方案

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



对于数组示例, foo + = 不会连接到存储在 foo ,你会做 foo.concat(['a'])。相反,它正在创建一个新数组,并为其分配 foo 。 Array类的文档提到了哪些方法使数组变异,并返回一个新数组。


I am a little confused about object assignment and pointers in Ruby, and coded up this snippet to test my assumptions.

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

I had assumed that when I assigned bar to beans, it would create a copy of the object, and modifying one would not affect the other. Alas, the output shows otherwise.

^_^[jergason:~]$ ruby test.rb 
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
#<Foo:0x100155c60>
2
2

I believe that the numbers have something to do with the address of the object, and they are the same for both beans and bar, and when I modify beans, bar gets changed as well, which is not what I had expected. It appears that I am only creating a pointer to the object, not a copy of it. What do I need to do to copy the object on assignment, instead of creating a pointer?

Tests with the Array class shows some strange behavior as well.

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}"

This produces the following wonky output:

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

This blows my mind. Calling pop on foo affects baz as well, so it isn't a copy, but concatenating something onto foo only affects foo, and not baz. So when am I dealing with the original object, and when am I dealing with a copy? In my own classes, how can I make sure that assignment copies, and doesn't make pointers? Help this confused guy out.

解决方案

There are a lot of questions in this question. The main thing to know is assignment never makes a copy in ruby, but methods often return new objects instead of modifying existing objects. For immutable objects like Fixnums, you can ignore this, but for objects like arrays or Foo instances, to make a copy you must do bar.dup.

As for the array example, foo += is not concatenating onto the array stored in foo, to do that you would do foo.concat(['a']). Instead, it is making a new array and assigning foo to that. The documentation for the Array class mentions which methods mutate the array in place and which return a new array.

这篇关于对象分配和指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆