我们在学校有一个项目,尽管项目涉及什么,但它涉及使用具有以下特定结构的链表:

typedef struct _node {
    int contents;
    _node *next_node;
} *node;

在项目开始之前,我们被分配了很多功能来学习如何使用列表(将节点推到列表的前面或后面,计算节点的数量,搜索特定的节点等)。

并不是那么困难,但是当老师发送基础项目时(以便我们每个人都在同一地方开始),所有功能都涉及通过引用传递*node 。例如:
resultType functionName(node *list, ...) { ... }

我使用 void 函数完成了项目之前的所有列表函数,因为至少据我所知,我们正在使用指针,因此,只要您不丢失列表头的内存地址,您就可以不会丢失内容(以及列表的其余部分)。

那么...在这种情况下将指针传递给指针的意义何在?有什么我想念的吗?我问我的老师,他不知道该怎么解释(要么那样,要么他像我一样迷路)。我的意思是,该结构已经是一个指针,因此,为什么要传递列表地址的地址?

最佳答案

这取决于在functionName函数中执行的操作。如果要分配给node*指针,或者要更改其值超出functionName的范围,则需要能够对其进行修改,并且需要将指向该指针的指针传递给函数。

为了举例说明,请比较下面的两个函数。第一个allocate1能够在指针a上进行堆分配,因为它接收了指向指针的指针。第二个allocate2按值接收指针,可以分配数组,但是返回后,分配的空间将丢失。通过比较print语句中的指针值可以看出这一点。

#include <iostream>

void allocate1(double** a, const int n)
{
    *a = new double[n];
    std::cout << "allocate1: " << *a << std::endl;
}

void allocate2(double* a, const int n)
{
    a = new double[n];
    std::cout << "allocate2: " << a << std::endl;
}

int main()
{
    double* test1 = nullptr;
    double* test2 = nullptr;
    int n = 10;

    allocate1(&test1, 10);
    std::cout << "after allocate1: " << test1 << std::endl;
    test1[3] = 16; // OK!

    allocate2(test2, 10);
    std::cout << "after allocate2: " << test2 << std::endl;
    test2[3] = 16; // NOT OK!

    return 0;
}

我的机器上的输出是:
allocate1: 0x7fcdd2403160
after allocate1: 0x7fcdd2403160
allocate2: 0x7fcdd24031b0
after allocate2: 0x0
Segmentation fault: 11

07-28 02:54
查看更多