C#中链表赋值后修改原变量为何不影响新变量?栈堆解析
链表合并方法中指针指向变化的原因与内存执行过程分析
问题场景
在实现链表合并的MergeTwoLists方法中,将方法参数list1赋值给局部变量l1,初始时二者均指向链表1->2->4->null。但首次进入while循环执行list1 = list1.next后,list1变为指向2->4->null,l1却仍指向原链表。以下是对该现象的原因分析,以及栈、堆内存的具体执行过程。
完整代码
using System; using System.Collections.Generic; using System.Collections; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LinkedList { public class ListNode { public int val; public ListNode next; public ListNode(int val = 0, ListNode next = null) { this.val = val; this.next = next; } } internal class Program { static void Main(string[] args) { ListNode list1= new ListNode(1, new ListNode(2, new ListNode(4, null))); ListNode list2 = new ListNode(1, new ListNode(3, new ListNode(4, null))); ListNode list3 = MergeTwoLists(list1,list2); } public static ListNode MergeTwoLists(ListNode list1, ListNode list2) { if (list1 == null) return list2; else if (list2 == null) return list1; ListNode l3 = new ListNode(0,null),l1=list1,l2=list2; ListNode l4 = l3; while (list1 != null && list2 != null) { if (list1.val <= list2.val) { l4.next = list1; list1 = list1.next; } else { l4.next = list2; list2 = list2.next; } l4 = l4.next; } l4.next=list1==null?list2:list1; return l3.next; } } }
核心原因
C#中引用类型的变量本质是存储堆对象地址的指针,变量赋值操作是复制这个地址值,而非让两个变量共享同一个存储空间:
- 执行
l1 = list1时,是把list1栈内存中存储的堆节点地址,复制到l1的栈内存中,此时二者指向同一个堆节点。 - 执行
list1 = list1.next时,是取出当前list1指向节点的next属性(即下一个堆节点的地址),并将这个新地址覆盖list1栈内存中的旧地址。这个操作只修改了list1变量的存储值,不会影响l1栈内存中已保存的原地址,因此l1依然指向原链表头节点。
栈、堆内存执行过程
方法调用时的栈初始化
调用MergeTwoLists方法时,栈上会为方法的参数(list1、list2)和局部变量(l3、l1、l2、l4)分配空间,这些变量都是指针,存储堆中ListNode对象的内存地址。初始赋值阶段
- 参数
list1的栈内存中,存储着堆中第一个ListNode(val=1,next指向val=2节点)的地址。 - 执行
l1 = list1后,l1的栈内存被写入和list1相同的地址,此时二者都指向堆中的同一个链表头节点。
- 参数
循环内的指针修改
进入while循环执行list1 = list1.next:- 先读取
list1栈内存中的地址,找到堆中对应的ListNode,取出其next属性(即val=2节点的堆地址)。 - 将这个新地址覆盖
list1的栈内存值,此时list1的栈值变为val=2节点的地址,而l1的栈值仍保留原val=1节点的地址,因此l1指向的链表没有变化。
- 先读取
堆内存的状态
整个过程中,堆中的ListNode对象(链表节点)本身没有被修改,所有操作只是改变了栈上指针变量的指向,堆中的链表结构始终保持初始状态(1->2->4->null和1->3->4->null)。
内容的提问来源于stack exchange,提问作者Vikram Singh
相关产品推荐
相关产品推荐

