문제
다음 코드는 "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 페이지). 그것들은 그 값을 비슷하게 변경하지만 위에서 제안한 결과를 얻습니다. 우리는 같은 문제에 대해 말하고 있습니까?
해결책
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"
루비에서는 정수 객체가 불변이기 때문에 정수를 여러 참조에 할당하고 그 후에 그 값을 변경할 수 없습니다.
@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
루비에서는 기준이 변이 가능하고 정수는 (정확히 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__
.
그들은 같은 메모리 위치를 가리키지 않습니다. 루비는 참조로 통과하지 않습니다.
첫 번째 줄 후에 A, B, C 및 D는 모두 동일한 FixNum 객체 (값 7)를 가리 킵니다. 그러나 B = 8을 실행할 때 B는 이제 새로운 FixNum 객체 (값 8)를 가리 킵니다.
효과적으로 기존 객체를 변형시키는 대신 B를 새 개체에 할당합니다. 이것이 예상대로 변경이 전파되지 않는 이유입니다.
C ++와 비교하는 경우, 이것은 참조별로 할당하는 대신 값별로 포인터를 할당하는 것과 같습니다.
나는 독서를 강력히 추천합니다 C 참조 자바와 루비는 그렇지 않습니다