Question

Je m'attendais à ce que le code suivant indique "8", "111" et "999". J'ai supposé que chacun a, b, c et d pointe vers le même emplacement de mémoire. Si je change de lieu par l’un d’eux, pourquoi l’autre ne changerait-il pas? Clairement, ma logique est mauvaise ou j'ai oublié quelque chose. Il imprime "7", "7". et "8", à la place.

Pourquoi?

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

     c  = 111
     puts a

     d  =  999
     puts b

[Précision]

La cause de ma confusion est l’exemple de du livre (page 20). Ils y changent les valeurs de la même manière, mais ils obtiennent les résultats que j'ai suggérés ci-dessus. Parlons-nous du même problème?

Était-ce utile?

La solution

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"

dans Ruby, l’objet Integer étant immuable, vous ne pouvez pas attribuer un Integer à plusieurs références et modifier sa valeur après.

Comme @pts l'a suggéré, vous devriez utiliser un tableau pour envelopper votre référence Integer car les tableaux sont mutables, vous pouvez changer la valeur après.

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

CLARIFICATION:

Si vous venez d'un arrière-plan C ++, cela peut paraître étrange car C ++ fait 2 choses avec la même syntaxe, attribuant la référence et modifiant la valeur référencée.

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

En Ruby, les références sont modifiables et les entiers ne le sont pas (exactement le contraire de C ++). Donc, assigner une référence changera réellement la référence et non la valeur référencée.

Une autre solution serait de créer une classe qui est un entier mutable:

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

Autres conseils

Le moyen le plus simple d'obtenir le résultat attendu consiste à utiliser un tableau à un seul élément:

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

Pour obtenir si a et b font référence au même objet, utilisez a .__ id__ == b .__ id __ .

Ils ne pointent pas vers le même emplacement mémoire. Ruby ne passe pas par référence .

Après la première ligne, a, b, c et d pointent tous vers le même objet Fixnum (avec la valeur 7). Cependant, lorsque vous exécutez b = 8, b pointe maintenant vers un nouvel objet Fixnum (avec la valeur 8).

Effectivement, vous attribuez b à un nouvel objet, plutôt que de muter l'objet existant. C’est la raison pour laquelle vos modifications ne sont pas propagées comme prévu.

Si vous comparez avec C ++, cela revient à assigner un pointeur par valeur plutôt qu’à attribuer par référence.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top