Несколько ссылок в Ruby - PullRequest
1 голос
/ 03 мая 2009

Я ожидал, что следующий код выведет «8», «111» и «999». Я предположил, что каждый a, b, c и d указывает на одну и ту же ячейку памяти. Если я поменяю местоположение через одного из них, почему другой не поменяется? Понятно, что у меня плохая логика, или я что-то упустил. Вместо этого он печатает «7», «7» и «8».

Почему?

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

     c  = 111
     puts a

     d  =  999
     puts b

[Разъяснение]

Причиной моего замешательства является пример в книге (стр. 20). Они так же меняют значения, но получают результаты, которые я предложил выше. Мы говорим об одной и той же проблеме?

Ответы [ 5 ]

11 голосов
/ 03 мая 2009
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, вы должны использовать массив, чтобы обернуть вашу целочисленную ссылку, потому что массивы изменчивы, чтобы вы могли изменить значение после.

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 ++ делает 2 вещи с одинаковым синтаксисом, назначая ссылку и изменяя значение, на которое ссылаются.

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
2 голосов
/ 03 мая 2009

Самый простой способ получить ожидаемый результат - использовать одноэлементный массив:

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__.

1 голос
/ 27 августа 2009

Я настоятельно рекомендую прочитать C проходов по ссылке Java, а Ruby не

1 голос
/ 03 мая 2009

После первой строки a, b, c и d указывают на один и тот же объект Fixnum (со значением 7). Однако при выполнении b = 8 теперь b указывает на новый объект Fixnum (со значением 8).

Фактически вы назначаете b новому объекту, а не изменяете существующий объект. Вот почему ваши изменения не распространяются так, как вы ожидали.

Если вы сравниваете с C ++, это похоже на присвоение указателя по значению, а не по ссылке.

1 голос
/ 03 мая 2009

Они не указывают на одну и ту же область памяти. Руби не передается по ссылке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...