动态内存和链表
Posted
技术标签:
【中文标题】动态内存和链表【英文标题】:Dyamic memory & Linked Lists 【发布时间】:2015-05-08 09:08:57 【问题描述】:好的,假设我们在 C++ 中有一个链表实现。此外假设节点是一个类,列表本身是一个类,它看起来像这样:
#include <iostream>
using namespace std;
class List;
class Node
private:
Node(char, Node*);
char data;
Node* next;
friend class List;
friend ostream& operator<<(ostream&, const List&);
;
class List
public:
List(int = 0);
List(const List&);
~List();
bool gotoBeginning();
bool gotoEnd();
bool gotoNext();
bool gotoPrior();
bool insert(char);
bool remove(char&);
bool empty() const;
bool full() const;
bool clear();
List& operator=(const List&);
friend ostream& operator<<(ostream&, const List&);
private:
Node* head;
Node* cursor;
;
#endif
假设列表为空。 此外,假设我们刚刚在列表中插入了一个新元素“z”,这意味着列表当前有 1 个节点。
我们来看看插入函数:
bool List::insert(char item)
if(empty())
Node* newNode = new Node(item, NULL);
head = cursor = newNode;
return true;
else
// I dont need to show this part because the above code will suffice
好的,所以我们都知道,类型为指向节点的指针的变量 newNode 被分配了包含已存储在堆上的节点的内存位置。
现在记住我们刚刚创建了一个新节点,假设传递给插入函数的项目是'z'
内存分配 堆栈堆 | | | | \|/ \|/ 512 902 内存地址 | -----| |--->|-----|-----| | 902 | | | 'z'|空| |--------|----| |-----|-----| newNode (no name/newNode) 变量名(无名称):因为在堆上分配的内存只能通过指针直接访问。
我遇到的问题是这个。 newNode 指针是否在堆栈上创建并分配了一些内存地址,如 512,如上所示? 还是该指针从未在堆栈上分配(因此只需删除上面的 512)并且仅指向在堆上创建的内存(902)?
我问的原因是因为插入函数内部 if 语句中的第二行代码将 newNode 分配给 head 和 cursor
这让我很困惑。头部和光标现在会包含地址 512 还是 902?
如果我们继续在插入函数中的 else 语句中编写代码,那么它看起来像这样:
bool List::insert(char item)
if(empty())
Node* newNode = new Node(item, NULL);
head = cursor = newNode;
return true;
else
Node* newNode = new Node(item, NULL);
cursor = cursor->next = newNode; // what is this line doing
return true;
return false;
那么cursor->next
如何获取新节点的值,cursor
也获取新节点的值。
是的,上面的函数运行良好,我在项目中得到了 A,所以所有代码都是正确的,但我提到的概念让我很困扰
【问题讨论】:
【参考方案1】:new
返回的指针需要存储在某个地方,它存储在堆栈变量newNode
中。 newNode
的值,它的内容,就是new
返回的地址。
当您将一个指针分配给另一个指针时,复制的是指针的值、内容、指针指向的地址。
所以当你这样做时,例如
head = newNode;
那么head
将获得与newNode
相同的值,并将指向new
表达式分配的内存。
举个小例子:假设你有两个指针:
int* a;
int* b;
你分配一些内存并分配给a
:
a = new int;
现在内存看起来像这样:
+---+ +------------------+ |一个 | --> |分配的内存 | +---+ +------------------+然后你从a
分配到b
:
b = a;
那么内存看起来是这样的:
+---+ |一个 | -。 +---+ | +------------------+ >>-> |分配的内存 | +---+ | +------------------+ |乙 | -' +---+变量a
和b
的确切存储位置并不重要,它们指向的位置也不重要。
【讨论】:
好吧,这肯定有帮助,但我仍然对 cursor->next 如何接收 newNode 的地址感到困惑。然后它被分配 newNode, cursor = newNode @fsolano94 函数启动时,列表不为空,那么cursor
指向一个节点(应该是最后一个节点),也就是说cursor->next = newNode
会取最后一个节点,make它的next
指针指向newNode
指向的位置。然后,您将 cursor->next
指向的内容分配给 cursor
,使 cursor
再次指向列表中的最后一个节点。但是,该表达式存在问题(请参阅下一条评论)。
@fsolano94 cursor = cursor->next = newNode
的问题在于它可以被评估为cursor = (cursor->next = newNode)
(这是预期和希望的),但它也可能是(cursor = cursor->next) = newNode
,即 不是你所期望的,最后会导致问题。您需要显式添加括号以确保完成正确的操作。
下一条评论?您是否发布更多详细信息
好的,感谢您提供的所有帮助 Joachim Pileborg 和好名字顺便说一句。 :)【参考方案2】:
cursor = cursor->next = newNode; // what is this line doing
请注意,分配不会同时发生。它从右向左传播。下面是一段更冗长的代码,与上面的代码行相同:
Node* oldNode = cursor;
cursor = newNode;
oldNode->next = newNode;
在某些情况下(重载的赋值运算符),按顺序写下来甚至可能是有益的。
【讨论】:
以上是关于动态内存和链表的主要内容,如果未能解决你的问题,请参考以下文章