面试题答案
一键面试指针方式
- 节点创建:
- 需要在堆上动态分配内存来存储节点对象,例如使用
new
关键字(在C++中)。假设自定义类为Node
,代码如下:
Node* newNode = new Node(); newNode->next = nullptr;
- 这里
new
操作符会在堆上分配一块足够存储Node
对象的内存,并返回指向这块内存的指针。
- 需要在堆上动态分配内存来存储节点对象,例如使用
- 节点销毁与内存释放:
- 当节点不再需要时,需要手动释放内存。在C++中,使用
delete
关键字:
Node* current = head; Node* next; while (current!= nullptr) { next = current->next; delete current; current = next; }
delete
操作符会调用节点对象的析构函数(如果有定义),然后释放该节点在堆上占用的内存。如果忘记调用delete
,会导致内存泄漏。
- 当节点不再需要时,需要手动释放内存。在C++中,使用
引用方式
- 节点创建:
- 由于引用必须在定义时初始化,所以创建节点时需要有一个已经存在的节点作为其
next
引用的目标。假设已经有一个prevNode
,代码如下:
Node newNode; Node& refNext = newNode.next; refNext = prevNode;
- 这里
newNode
对象通常在栈上分配内存(如果在函数内部定义),而不是在堆上动态分配(除非使用new
在堆上创建,这与引用的常规使用场景不太符合)。
- 由于引用必须在定义时初始化,所以创建节点时需要有一个已经存在的节点作为其
- 节点销毁与内存释放:
- 如果节点对象是在栈上创建的,当它所在的作用域结束时,会自动调用其析构函数并释放内存。例如:
{ Node newNode; // 链表操作 } // newNode对象在这里自动销毁,无需手动释放内存
- 如果使用
new
在堆上创建对象并使用引用,管理会变得复杂,因为引用不能重新绑定,可能需要额外的机制来处理对象的销毁。例如:
Node* heapNode = new Node(); Node& ref = *heapNode; //... delete heapNode;
- 这里虽然使用了引用,但最终还是需要像指针方式一样手动释放堆上的内存,否则会导致内存泄漏。而且如果不小心将引用指向其他对象,可能会引发未定义行为。
总结来说,指针方式更灵活,可在堆上动态创建和管理节点,但需要手动释放内存;引用方式在栈上创建节点时内存管理相对简单,但使用场景相对受限,并且在堆上使用时与指针方式在内存释放上类似,同样需要手动处理。