prev 指针不适用于我使用 GList 的堆栈

prev pointer not working for my stack using GList

我正在使用 GList(双重)实现一个堆栈,但是当我使用 g_list_last(*stack*) 为我的堆栈分配最后一个元素时,程序根本不打印我的堆栈

使用 g_list_first(*stack*) 指向第一个元素有效,我可以使用 stack->next pointer

遍历

这是我的测试程序:

#include <iostream>
#include <cstdlib>
#include <glib.h>

using namespace std;

int main()
{
        cout << "Enter the no of random data to push: ";
        int number = 0;
        cin >> number;

        GList *stack = nullptr;
        for (int i = 0; i < number; i++) {
                int data = random() % 10;
                stack = g_list_append(stack, GINT_TO_POINTER(data));
                cout << "Push: " << data << endl;
        }

        cout << "Printing the stack forward:\n";
        stack = g_list_first(stack);
        while (stack != nullptr) {
                cout << GPOINTER_TO_INT(stack->data);
                cout << "->";
                stack = stack->next;
        }
        cout << "nullptr" << endl;

        cout << "Printing the stack backward:\n";
        stack = g_list_last(stack);
        while (stack != NULL) {
                cout << GPOINTER_TO_INT(stack->data);
                cout << "->";
                stack = stack->prev;
        }
        cout << "nullptr" << endl;

        return 0;
}

我是否必须在追加时手动分配上一个 link?

首先,我不推荐在 C++ 代码库中使用 GLib; GLib 是一个 C 库,充满了惯用的 C 代码和功能。我建议改用 C++ 标准库。

GList是一个双向链表,每个元素由三个指针组成:

typedef struct _GList GList;
struct _GList
{
  void *data; // untyped pointer data
  GList *prev; // pointer to the previous element in the list
  GList *next; // pointer to the next element in the list
}

为方便起见,所有 GList 函数都接受 NULL 作为有效列表;在 g_list_append() 的情况下,传递一个 NULL 列表作为第一个参数意味着它将为您传递的数据分配一个新的 GList 元素并将其放在列表。

在您的代码中,您在填充列表后获取列表的头部,并调用 g_list_first(),这是列表头部的空操作;然后你继续通过迭代来使用它,直到你到达列表的末尾,在那里你将 nullptr 分配给 stack 变量。由于 nullptr/NULL 是一个有效的空 GList,您现在在一个有效但空的列表上调用 g_list_last(),它将 return NULL,从而防止你向后迭代。此外,您现在正在泄漏分配给列表的内存。

解决方案是 从不 使用包含列表头部的相同变量迭代 GList

        cout << "Printing the stack forward:\n";
        GList *iter = g_list_first(stack);
        while (iter != nullptr) {
                cout << GPOINTER_TO_INT(iter->data);
                cout << "->";
                iter = iter->next;
        }
        cout << "nullptr" << endl;

上面的代码将使用 iter 变量,而不是 stack。这意味着下面的代码:

        cout << "Printing the stack backward:\n";
        iter = g_list_last(stack);
        while (iter != NULL) {
                cout << GPOINTER_TO_INT(iter->data);
                cout << "->";
                iter = iter->prev;
        }
        cout << "nullptr" << endl;

将正常工作,并向后遍历堆栈,因为 stack 变量仍然指向列表的头部,并且您现在正在使用一个临时迭代器。

记得调用列表上的 g_list_free() 来释放分配给它的任何资源——如果您也在分配 data 指针的内容,请记得调用 g_list_free_full()