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