我期望以下代码打印“8”,“111”和“111”。和“999”。我认为每个a,b,c和d指向相同的内存位置。如果我通过其中一个改变位置,为什么另一个不改变?显然,我的逻辑很差,或者我忽略了一些东西。它打印“7”,“7”和“7”。而“8”代替。

为什么?

a=b=c=d=7
     b  =  8
     puts d

     c  = 111
     puts a

     d  =  999
     puts b

<强> [澄清]

我混淆的原因是这本书的例子。 20)。他们在那里改变了类似的值,但是他们得到了我上面建议的结果。我们是否谈到同样的问题?

有帮助吗?

解决方案

a=b=c=d=7
# a, b, c and d points to the same integer object "7"
     b  =  8
# b now points to a new object "8"
# "=" does not change the value of the pointer integer, 
# it assings a new reference like in the line above
     puts d
# obviously, d still points to "7"

     c  = 111
# c now points to another integer object "111"
     puts a
# a still points to "7"

     d  =  999
# d now points to a new integer object "999"
     puts b
# b still points to "8"

在Ruby中,Integer对象是不可变的,因此您不能将Integer分配给多个引用并在之后更改其值。

正如@pts建议的那样,你应该使用一个数组来包装你的Integer引用,因为Arrays是可变的,你可以在之后改变它。

a=b=c=d=[7]
b[0] = 8
puts d[0]
c[0] = 111
puts a[0]
d[0] = 999
puts b[0]

澄清:

如果你来自C ++背景,可能会很奇怪,因为C ++使用相同的语法做两件事,分配引用并更改引用的值。

int a = 10; // creates an int on the stack with value 10
int& b = a; // creates a reference to an int and references the a variable
b = 5; // change the value referenced by b (so a) to 5
// a and b now hold the value 5

在Ruby中,引用是可变的,而整数则不是(与C ++完全相反)。因此,分配引用实际上会更改引用而不是引用的值。

另一个解决方案是创建一个可变整数的类:

class MutableInteger
  attr_writer :value
  def initialize(value)
    @value = value
  end
  def inspect
    value
  end
  def to_i
    value
  end
  def to_s
    value
  end
end

a = b = MutableInteger.new(10)
a.value = 5
puts b
# prints 5

其他提示

获得预期输出的最简单方法是使用单元素数组:

a=b=c=d=[7]
b[0] = 8
puts d[0]
c[0] = 111
puts a[0]
d[0] = 999
puts b[0]

要获得a和b是否引用同一个对象,请使用 a .__ id __ = b .__ id __

它们不指向相同的内存位置。 Ruby未通过引用传递。

在第一行之后,a,b,c和d都指向相同的Fixnum对象(值为7)。但是,当您执行b = 8时,b现在指向一个新的Fixnum对象(值为8)。

有效地,您将b分配给新对象,而不是改变现有对象。这就是您的更改未按预期传播的原因。

如果您正在与C ++进行比较,这就像按指定值指针,而不是按引用分配。

我强烈建议您阅读 C通过引用传递Java和Ruby不会

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top