简体   繁体   English

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

[英]Why does popping from one stack actually pop from multiple separate stacks?

I have tried to simplify and annotate the code which is giving me a headache below. 我试图简化和注释代码,这让我头疼不已。 It demonstrates my problem. 它证明了我的问题。 Simply put, I have two separate stacks and I am trying to pop from one stack. 简而言之,我有两个单独的堆栈,我试图从一个堆栈中弹出。 For some reason, when you pop one of the stacks, it actually seems to pop the other one as well?! 由于某种原因,当您弹出其中一个堆栈时,实际上似乎也弹出了另一个堆栈? Is this by design and if so, why and how should I work around it? 这是设计使然吗,如果是这样,为什么以及应该如何解决?

... or am I just being a muppet? ...还是我只是个木偶? (don't answer that one) (不要回答那个)

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

This line is your culprit. 这条线是您的罪魁祸首。 _stackCopy and _stackMaster are each references to stack instances. _stackCopy_stackMaster都是对堆栈实例的引用 When you assign one to the other, you are making them each reference the same instance . 当您将一个分配给另一个时,就是使它们各自引用同一实例 What you want to do is Clone _stackMaster and assign THAT to _stackCopy . 您要做的是克隆_stackMaster并将THAT分配给_stackCopy

_stackCopy = _stackMaster.Clone()

You've run into the difference between value types and reference types. 您已经遇到了值类型和引用类型之间的差异。 Stack is a reference type, meaning that assigning _stackCopy to _stackMaster doesn't copy the stack, but only copies a reference to the exact same location in memory. 堆栈是一种引用类型,这意味着将_stackCopy分配给_stackMaster不会复制堆栈,而只会将引用复制到内存中完全相同的位置。

When you are performing the last Pop, you are only performing it on one stack, but at that point in your code, _stackCopy and _stackMaster point to exactly the same object. 当您执行最后一个Pop时,您只在一个堆栈上执行它,但是在代码中,此时_stackCopy和_stackMaster指向完全相同的对象。

You could get around this by doing (in C#): 您可以通过执行以下操作(在C#中)解决此问题:

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

This is because you are simply assigning the reference to _stackCopy. 这是因为您只是将引用分配给_stackCopy。 This line does not copy the stack, it just copies the reference to the actual object: 该行不复制堆栈,而只是将引用复制到实际对象:

_stackCopy = _stackMaster

In .NET, you have reference and value types. 在.NET中,您具有引用和值类型。 A value type will be copied if you assign it to another variable. 如果将值类型分配给另一个变量,则会将其复制。 For a reference type, you copy the reference, but you still only have one object. 对于引用类型,可以复制引用,但是仍然只有一个对象。

So yes, the behaviour you are seeing, is by design. 是的,您所看到的行为是设计使然。

I have not used VB.net much, but it appears you are not doing a deep copy, you are only copying by reference. 我没有使用VB.net太多,但是看来您没有在进行深层复制,只是通过引用进行复制。 Here's an analogy: 这是一个比喻:

With your first stack, you have a box that contains items. 在第一个堆栈中,您有一个包含项目的盒子。 When you are creating your copy, you are not getting another box and putting the same items in, you are instead creating a sign that says "Look at that box" and points to your original copy. 创建副本时,您不会再得到另一个盒子并将相同的物品放进去,而是要创建一个标有“看着那个盒子”并指向原始副本的标牌。 Thus, when you take something about of the box, when you follow the sign of course an item will be missing. 因此,当您拿起盒子的东西时,当您顺着指示牌走时,当然会丢失一个物品。

Try googling "pass by reference". 尝试谷歌搜索“通过引用”。 They are used a lot in Object Oriented Languages. 它们在面向对象的语言中大量使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM