【问题标题】: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-&gt;next如何获取新节点的值,cursor也获取新节点的值。

是的,上面的函数运行良好,我在项目中得到了 A,所以所有代码都是正确的,但我提到的概念让我很困扰

【问题讨论】:

    标签: c++


    【解决方案1】:

    new 返回的指针需要存储在某个地方,它存储在堆栈变量newNode 中。 newNode的值,它的内容,就是new返回的地址。

    当您将一个指针分配给另一个指针时,复制的是指针的值、内容、指针指向的地址。

    所以当你这样做时,例如

    head = newNode;
    

    那么head 将获得与newNode 相同的值,并将指向new 表达式分配的内存。


    举个小例子:假设你有两个指针:

    int* a;
    int* b;
    

    你分配一些内存并分配给a

    a = new int;
    

    现在内存看起来像这样:

    +---+ +------------------+ |一个 | --> |分配的内存 | +---+ +------------------+

    然后你从a分配到b

    b = a;
    

    那么内存看起来是这样的:

    +---+ |一个 | -。 +---+ | +------------------+ >>-> |分配的内存 | +---+ | +------------------+ |乙 | -' +---+

    变量ab 的确切存储位置并不重要,它们指向的位置也不重要。

    【讨论】:

    • 好吧,这肯定有帮助,但我仍然对 cursor->next 如何接收 newNode 的地址感到困惑。然后它被分配 newNode, cursor = newNode
    • @fsolano94 函数启动时,列表不为空,那么cursor指向一个节点(应该是最后一个节点),也就是说cursor-&gt;next = newNode会取最后一个节点,make它的next 指针指向newNode 指向的位置。然后,您将 cursor-&gt;next 指向的内容分配给 cursor,使 cursor 再次指向列表中的最后一个节点。但是,该表达式存在问题(请参阅下一条评论)。
    • @fsolano94 cursor = cursor-&gt;next = newNode 的问题在于它可以被评估为cursor = (cursor-&gt;next = newNode)(这是预期和希望的),但它也可能是(cursor = cursor-&gt;next) = newNode,即 不是你所期望的,最后会导致问题。您需要显式添加括号以确保完成正确的操作。
    • 下一条评论?您是否发布更多详细信息
    • 好的,感谢您提供的所有帮助 Joachim Pileborg 和好名字顺便说一句。 :)
    【解决方案2】:
    cursor = cursor->next = newNode; // what is this line doing
    

    请注意,分配不会同时发生。它从右向左传播。下面是一段更冗长的代码,与上面的代码行相同:

    Node* oldNode = cursor;
    cursor = newNode;
    oldNode->next = newNode;
    

    在某些情况下(重载的赋值运算符),按顺序写下来甚至可能是有益的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-08
      • 2019-10-14
      • 2014-09-29
      • 2013-04-14
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多