链表头结点指向失败
情况一:Node ans = new Node(); Node headAns = ans;
当你使用 Node ans = new Node(); 时,你在内存中创建了一个新的 Node 对象实例,并且 ans 变量存储了这个新对象在内存中的地址。
然后 Node headAns = ans; 这行代码做的事情是,将 headAns 也赋值为 ans 所存储的内存地址。也就是说,此时 ans 和 headAns 都指向了同一个刚创建的 Node 对象,它们共享这个对象的内存地址。
当你后续通过 ans = ans.next; 来移动 ans 指针沿着链表前进时,比如假设 next 指向了链表中的下一个节点,那么 ans 就会更新为指向新的节点,但 headAns 并没有被改变,它仍然指向最初的那个节点,也就是整个链表的头节点。
这是因为 headAns 只是存储了一个内存地址,当你没有对它进行重新赋值操作时,它就会一直保持指向最初的那个对象,也就是链表的头节点。
情况二:Node ans = null; Node headAns = ans;
在这里,Node ans = null; 表示 ans 初始化为一个空指针,它不指向任何有效的内存地址,也就是没有指向任何实际的 Node 对象。
然后 Node headAns = ans; 使得 headAns 也被初始化为同样的空指针状态。
当你后续尝试通过 ans = ans.next; 来移动 ans 指针时,因为 ans 最初就是空指针,所以 ans.next 这种操作是非法的(会导致程序崩溃,通常会抛出空指针异常之类的错误,具体取决于编程语言),在假设没有发生这种错误并且我们继续分析的情况下,即使 ans 被赋予了某个新的节点地址(假设通过其他正确的方式给 ans 赋值了一个有效的节点地址),headAns 仍然保持为空指针,因为它没有被重新赋值过,它始终指向最初的那个空状态,也就是它不会自动跟着 ans 的赋值变化而变化,始终保持为 null。
所以总结来说,在这两种情况下,关键的区别在于最初 ans 是否指向了一个实际的对象(通过 new Node() 创建的情况)还是初始化为空指针(null)的情况。当 ans 初始化为空指针时,后续的操作如果没有正确地更新 headAns,它就会一直保持为空指针状态,而不会指向实际构建的链表的头节点。
Node ans = new Node(); Node headAns = ans;
这样写,ans链表添加节点next,ans = ans.next,headAns可以指向一整个链表的头结点。
Node ans = null; Node headAns = ans;
这样写,ans链表添加节点next,ans = ans.next,headAns不可以指向一整个链表的头结点,始终为null
变量=null会赋值内存地址吗
不会
当你将一个变量赋值为 null(在支持 null 概念的编程语言中,比如 Java、C# 等),它并不会被赋予一个有效的内存地址来指向实际的数据对象。
相反,null 表示该变量不指向任何有效的内存位置,也就是它没有引用任何实际存在的对象或数据结构。
例如在 Java 中:
class MyClass {
// 类的定义内容
}
MyClass obj = null;
这里的 obj 变量被初始化为 null,此时它在内存中并没有一个有效的内存地址与之对应,它仅仅是一个空的引用,表示目前没有指向任何 MyClass 的实例对象。
在 C++ 中,虽然没有直接等同于 null 的概念,但有类似的空指针表示方式,比如 nullptr:
class MyClass {
// 类的定义内容
};
MyClass* obj = nullptr;
这里的 obj 指针被初始化为 nullptr,同样意味着它不指向任何有效的 MyClass 对象,也就是没有一个有效的内存地址与之关联,它只是一个空指针的状态,表示当前未指向任何实际的内存区域来获取 MyClass 对象相关的数据。
所以,将变量赋值为 null(或类似的空指针表示形式)是表示该变量当前不具有有效的内存地址指向,而不是被赋予了一个特定的内存地址。



















