提问人:Nikkolasg 提问时间:12/9/2014 更新时间:12/9/2014 访问量:72
Ruby 引用和值传递
Ruby Reference & Value pass by
问:
我知道有很多类似的问题被问到。我已经阅读了它们,但仍然不明白为什么我的代码会这样做。它仅用于训练,我已经实现了一个简单的 LinkedList(单个链接),我想实现两个这样的排序列表的合并。代码如下
#!/usr/bin/ruby
#
module LinkedList
class Node
attr_accessor :next,:data
def to_s
s = @data.to_s + " -> "
s += @next.to_s if @next
s
end
end
end
def append tail, node
tail.next = node
tail = node
node = node.next
end
def merge_lists2 list1, list2
tail = LinkedList::Node.new
while(list1 && list2)
list1.data <= list2.data ? list1 = append(tail,list1) : list2 = append(tail,list2)
puts list1
puts list2
puts tail
puts "#######################################################"
STDIN.gets
end
if list1
tail.next = list1
elsif list2
tail.next = list2
end
tail.next
end
def generateList times = 3,factor = 1
list = LinkedList::Node.new
list.data = 0
curr = list
(1..times).each do |i|
curr.next = LinkedList::Node.new
curr = curr.next
curr.data = i*factor
end
list
end
def main
l1 = generateList 4,2
l2 = generateList 5,1.5
puts l1
puts l2
l3 = merge_lists2 l1,l2
puts l3
end
以下代码是我的“旧”版本:
def append tail, node
tail.next = node
tail = node
node = node.next
end
def merge_lists2 list1, list2
tail = LinkedList::Node.new
while(list1 && list2)
list1.data <= list2.data ? append(tail,list1) : append(tail,list2)
在旧版本中,它以无限循环运行,因为 list1 和 list2 从未更新过,因此 while 循环一直在进行。它们从未更新过,因为 list1 和 list2 变量被分配给 append 函数中的不同对象,因此当从函数返回时,list1 和 list2 会“收回”它们的原始引用。 但是“尾巴”参考更新了!!你可以通过运行代码看到它,你会看到 tail 始终是新合并列表的“tail”,而不是新列表的“head”。我不明白为什么,因为 tail 也在 append 中引用了一个新对象,所以当从函数返回时,“tail”应该仍然是“head”(哈哈,这太疯狂了)
谢谢。。。
答:
Ruby 的问题在于它向你隐瞒了很多东西。对象被传入,看似是引用,但实际上是巧妙伪装的指针。当您“取消引用”指针时,您可以操作原始数据,这与引用不同。与C++不同,Ruby不会特意提醒你这是这种情况。
因此,这意味着方法的参数只是行为类似于指向对象的指针的变量。将它们更改为其他值不会影响原始值。对它们调用方法或更改属性确实会影响原始方法,它们已被取消引用。
这里的实现存在很多问题。首先,像这样的方法应该是 Node 类的一部分:append
class Node
def append(list)
node = @data
while (node)
if (node.next)
node = node.next
else
node.next = list
return self
end
end
end
end
只要你没有循环列表,这应该可以工作。请注意,该值永远不会被修改,它只是集成的。list
请注意,此方法适用于单个节点(一个元素列表)和由多个节点组成的较长列表。通常,在编程中,您会尽量避免处理特殊情况,因此这会最大限度地减少编写和正常工作所需的代码。append
评论
ref String myVar
tail.next
@
@tail
tail
评论