为什么从一个堆栈弹出实际上是从多个单独的堆栈弹出的?

问题描述:

我试图简化和注释下面给我头痛的代码。它证明了我的问题。简而言之,我有两个单独的堆栈,我试图从一个堆栈弹出。出于某种原因,当你弹出其中一个堆栈时,它似乎也弹出另一个堆栈?!这是否是设计的,如果是这样,为什么以及如何解决它?为什么从一个堆栈弹出实际上是从多个单独的堆栈弹出的?

...还是我只是在尽一个布偶? (不要回答那个)

Public Class Form1 
Public _stackMaster As New Stack 
Public _stackCopy As New Stack 
Public _strPopped As String 

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    _stackMaster.Push("line1") 
    _stackMaster.Push("line2") 
    _stackMaster.Push("line3") 
    MsgBox("Before copying the Master stack to the Copy stack." & vbCrLf & "_stackMaster.Count=" & _stackMaster.Count & vbCrLf & "_stackCopy.Count=" & _stackCopy.Count) 
    _stackCopy = _stackMaster 
    MsgBox("After copying the Master stack to the Copy stack." & vbCrLf & "_stackMaster.Count=" & _stackMaster.Count & vbCrLf & "_stackCopy.Count=" & _stackCopy.Count) 
    _strPopped = _stackCopy.Pop 
    MsgBox("After popping a string from the Copy stack." & vbCrLf & "_stackMaster.Count=" & _stackMaster.Count & vbCrLf & "_stackCopy.Count=" & _stackCopy.Count & vbCrLf & "Why do both counts decrease?? Aren't they separate stacks?") 
    End 
End Sub 
End Class 

_stackCopy = _stackMaster 

这条线是你的罪魁祸首。 _stackCopy_stackMaster各自参考堆栈实例。当你将一个分配给另一个时,你正在使它们每个参考相同的实例。你想要做的是克隆_stackMaster并将其分配给_stackCopy

_stackCopy = _stackMaster.Clone() 
+0

这绝对是正确的。但是,没有任何人知道为什么吗?如果我有两个整数和我使用类似的赋值语句,它复制值,而不是参考。是在vb中声明一个栈基本上只是声明一个指针? – Chris 2009-08-19 12:50:51

+0

.NET有两种对象类型:引用类型和值类型。值类型在堆栈上分配(并从基类ValueType派生),而引用类型在堆上分配(并从基类对象派生),并在堆栈上分配一个引用(基本上是一个托管指针)。基元(Int32,Single,Double等)是值类型,因此直接分配。 'Stack'是一个引用类型,因此'Stack'变量都只是引用。 – 2009-08-19 17:27:30

这是因为您只是将引用分配给_stackCopy。这条线不会复制栈,它只是复制引用到实际对象:

_stackCopy = _stackMaster 

在.NET中,你有参考和值类型。如果将其分配给另一个变量,则值类型将被复制。对于引用类型,您复制引用,但仍只有一个对象。

所以,是的,你所看到的行为,是由设计。

你碰到的值类型和引用类型之间的差异。 Stack是一个引用类型,这意味着将_stackCopy分配给_stackMaster不会复制堆栈,而只是将引用复制到内存中完全相同的位置。

当你正在执行的最后流行,你只在一个堆栈执行,但在你的代码,_stackCopy和_stackMaster点完全相同的对象这一点。

你可以解决这个做(在C#):

object[] values = _stackMaster.ToArray(); 
for(int i = 0; i < values.Length; i++) 
{ 
    _stackCopy.Push(values[i]); 
} 
+0

+1对于实际解释复制参考实际上意味着什么和提供解决方案。 – 2009-08-18 20:32:08

+0

如果我可以,我会+1,但我不能,因为我还是菜鸟:(Thx的BG信息,非常实用。 – Kez 2009-08-19 18:44:08

我没用过VB.net不多,但它似乎你是不是做了深刻的副本,你是通过参考之用复制。这里有一个比喻:

你的第一个堆栈,你有一个包含项的复选框。当您创建副本时,您没有获得另一个方框并放入相同的项目,而是创建一个标志,指出“查看该方框”并指向您的原始副本。因此,当你拿起盒子的东西,当你按照标志当然一个项目将失踪。

尝试谷歌搜索“按引用传递”。它们在面向对象语言中使用很多。