通过引用从数组传递链表

时间:2017-07-10 20:17:00

标签: c++ arrays pointers reference linked-list

我的问题是,当试图添加到数组中的链表时,它似乎不起作用,我几乎完全不知道为什么会这样。首先,我声明对象move,如下所示:

struct move {
    move(int startX, int startY, int endX, int endY)
    {
        this->startX = startX;
        this->startY = startY;
        this->endX = endX;
        this->endY = endY;
        this->next = nullptr;
    }
    move()
    {
        next = nullptr;
        this->startX = -1;
    }
    int startX;
    int startY;
    int endX;
    int endY;
    move* next;
};

然后我声明了2个数组,一个包含100个move对象的链表,另一个包含指向第一个数组中每个链表中元素的指针。如下所示:

move possibleMoves[100];
move * endOfLists[100];

然后我将这些数组初始化如下所示:

for (int i = 0; i < 100; i++) {
    possibleMoves[i] = move();
    endOfLists[i] = &possibleMoves[i];
}

转到函数本身,它添加到possibleMoves数组中的一个链接列表,我将其原型化为:

void listAdd(move * list, move * object, int width);

我称之为:

if (possibleMoves[0].startX == -1) {
    possibleMoves[0] = *(new move(x, y, x + xOffset, y + yOffset));
}else {
    listAdd(endOfLists[width], new move(x, y, x + xOffset, y + yOffset), width);
}

该函数声明如下:

void listAdd(move * list, move * object, int width) {
    int count = 0;
    while (list->next != nullptr){
        count++;
        list = (*list).next;
    }
    std::cout << "\nCount: " << count << std::endl;
    list->next = object;
    endOfLists[width] = list->next;
}

计数总是输出为'0'。 这是所有代码(https://pastebin.com/E5g58N6L)的链接,它并不漂亮。在第188,197和444行调用listAdd过程。这是MCVE:

#include<stdio.h>
#include <stdlib.h>
#include<math.h>
#include<iostream>

    struct move {
        move(int startX, int startY, int endX, int endY)
        {
            this->startX = startX;
            this->startY = startY;
            this->endX = endX;
            this->endY = endY;
            this->next = nullptr;
        }
        move()
        {
            next = nullptr;
            this->startX = -1;
        }
        int startX;
        int startY;
        int endX;
        int endY;
        move* next;
    };
void listAdd(move * list, move * object, int width);
move possibleMoves[100];
move * endOfLists[100];

int main() {
    int x = 0;
    int y = 0;
    int xOffset = 1;
    int yOffset = 1;
    int width = 0;
    for (int i = 0; i < 100; i++) {
        possibleMoves[i] = move();
        endOfLists[i] = &possibleMoves[i];
    }
    if (possibleMoves[0].startX == -1) {
        possibleMoves[0] = *(new move(x, y, x + xOffset, y + yOffset));
    }else {
        listAdd(endOfLists[width], new move(x, y, x + xOffset, y + yOffset), width);
    }

void listAdd(move * list, move * object, int width) {
    int count = 0;
    while (list->next != nullptr) 
    {
        count++;
        list = (*list).next; //Go down the list until it reaches an item with nothing next.
    }

    std::cout << "\nCount: " << count << std::endl;
    list->next = object;
    endOfLists[width] = list->next;
}

1 个答案:

答案 0 :(得分:1)

NM完整代码。您没有告诉我们初始width是什么,但假设它有效(即-1<width<100),则无关紧要。看看这里发生了什么(添加功能结束):

list->next = object;

此时list endOfLists[width]。现在,你正确地设置了新对象的下一个,到目前为止一直很好。

但现在呢?

endOfLists[width] = list->next;

那么保存在全局中的“head”指针(为什么?)绕过它最初指向的(谁有一个正确的next!)并直接指向一个后代,新的对象为NULL 。我猜这不是你想要的:

  1. 内存泄漏0 - 在第一次静态分配时,如果你按照你做了很多的方式调用这个函数,这很快就会动态。
  2. 头部指针在函数末尾仍然是一个接下来是NULL的对象。确实是一个新的,但是下一个仍然是NULL - 所以下一个调用将执行相同的操作。
  3. 基本上你是在交换头部指针,同时泄漏记忆。你想要:

    1. 首先设置对象:object->next=endOfLists[width],然后将第二行设置为endOfLists[width]=object,使列表反转。
    2. 删除第二行,并保留原始头部。
    3. 另外:

      1. 我看不出全局的好理由
      2. 为什么add函数不是move方法?
      3. 您需要确保delete所有new个对象。
      4. 修改

        我看到了你的添加 - 第一次调用将始终返回0 ,因为所有初始对象都具有NULL nexts,即使你修复了代码。您需要至少两次调用同一索引(width)才能开始测试。

        图形附录​​

        一开始我们有100个对象,存储在一个数组中,所有这些都看起来像这样:

        head->list->NULL
        

        list这是endOfLists在某个索引处指向的对象,我们称之为指针head。现在,我们要添加新对象。我们输入加法函数,第一个参数为endOfLists[width],所以这将是函数本身的list参数。

        我们立即跳过while(因为我们的下一个已经是NULL)。到达上面的第一行,我们现在将头部连接到新对象:

        list->object->NULL
        

        所以在数组中我们有:

        head->list->object->NULL
        

        同样,head是存储在endOfLists[width]中的指针。现在我们告诉endOfLists[width]将头部交换到另一个头部,将其设置为list->next,这是对象。那么我们的记忆是怎样的呢?

        head->object->NULL
        list->^
        

        head(数组单元格)和list都指向对象,没有任何内容指向list。我们在那里泄漏。下次我们用更新的单元格调用函数时,我们将重复该过程,泄漏对象:

        head->     object2->NULL
        list->object->^
        

        等等。