Domanda

Mi aspettavo che il seguente codice stampasse "8", "111" e "999". Supponevo che ciascuno a, b, c e d punta alla stessa posizione di memoria. Se cambio la posizione attraverso una di esse, perché l'altra non dovrebbe cambiare? Chiaramente, la mia logica è scarsa o ho trascurato qualcosa. Stampa "7", "7" e "8", invece.

Perché?

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

     c  = 111
     puts a

     d  =  999
     puts b

[Chiarimento]

Il motivo della mia confusione è l'esempio nel il libro (pagina 20). Loro cambiano in modo simile i valori, ma ottengono i risultati che ho suggerito sopra. Stiamo parlando dello stesso problema?

È stato utile?

Soluzione

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"

in Ruby, l'oggetto Numero intero è immutabile, quindi non è possibile assegnare un numero intero a riferimento multiplo e modificarne il valore dopo.

Come suggerito da @pts, dovresti usare un array per racchiudere il tuo riferimento intero perché gli array sono mutabili e puoi cambiare il valore dopo.

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

PRECISAZIONE:

Se provieni da uno sfondo C ++, potrebbe essere strano perché C ++ fa 2 cose con la stessa sintassi, assegnando il riferimento e modificando il valore a cui si fa riferimento.

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

In Ruby, i riferimenti sono mutabili e gli interi no (esattamente il contrario di C ++). Quindi l'assegnazione di un riferimento cambierà effettivamente il riferimento e non il valore di riferimento.

Un'altra soluzione sarebbe quella di creare una classe che sia un intero mutabile:

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

Altri suggerimenti

Il modo più semplice per ottenere l'output previsto è l'utilizzo di un array a elemento singolo:

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

Per sapere se aeb si riferiscono allo stesso oggetto, usa a .__ id__ == b .__ id__ .

Non puntano alla stessa posizione di memoria. Ruby non passa per riferimento .

Dopo la prima riga, a, b, c e d puntano tutti allo stesso oggetto Fixnum (con valore 7). Tuttavia, quando si esegue b = 8, b ora punta a un nuovo oggetto Fixnum (con valore 8).

In effetti stai assegnando b a un nuovo oggetto, piuttosto che mutare l'oggetto esistente. Questo è il motivo per cui le modifiche non vengono propagate come previsto.

Se stai confrontando con C ++, è come assegnare un puntatore per valore, piuttosto che assegnare per riferimento.

Consiglio vivamente di leggere C passa per riferimento Java e Ruby no

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top