为什么指针对指针

Why pointer to pointer?

本文关键字:指针 为什么      更新时间:2023-10-16

一个非常普遍的问题:我想知道为什么要使用指针对指针?指向指针的指针将保存一个指针的地址,而该指针又将指向另一个指针。但是,这甚至可以通过使用单个指针来实现。

考虑以下示例:

{
int number = 10;
int *a = NULL;
a = &number;
int *b = a;
int *pointer1 = NULL;
pointer1 = b;  //pointer1 points to the address of number which has value 10
int **pointer2 = NULL;
pointer2 = &b;  //pointer2 points to the address of b which in turn points to the address of number which has value 10. Why **pointer2??
return 0;
}

我认为您回答了自己的问题,代码是正确的,您所评论的不是。

int number = 10;是值

int *pointer1 = b;指向保存int号的地址

int **pointer2 = &b;指向保存整数地址的地址

你看到这里的图案了吗??

address = * (single indirection)
address of address = ** (double  indirection)

以下表达式为true:

*pointer2 == b 
**pointer2 == 10 

以下不是!

*pointer2 == 10 

当您想更改指针指向函数外的内容时,指针对指针非常有用。例如

void func(int** ptr)
{
*ptr = new int;
**ptr = 1337;
}
int main()
{
int* p = NULL;
func(&p);
std::cout << *p << std::endl;   // writes 1337 to console
delete p;
}

一个愚蠢的例子展示了可以实现的目标:)只有一个指针是做不到的。

首先,指针不指向值。它指向内存位置(即它包含一个内存地址),而该内存位置又包含一个值。所以当你写的时候

pointer1 = b;

CCD_ 4指向与作为变量CCD_ 5的b相同的存储器位置。现在你执行

pointer2 = &b;

然后pointer2指向b的存储位置,该存储位置不包含10,而是变量number的地址

您的假设不正确。pointer2不指向值10,而是指向指针b的(地址)。使用*运算符取消对pointer2的引用将生成int *,而不是int

您需要指向指针的指针,原因与您首先需要指针的原因相同:在函数调用中实现引用传递参数,在数据结构之间实现数据共享,等等

在c中,对于更大的数据结构,这样的构造是有意义的。在C中的OOP中,由于缺乏在结构中实现方法的可能性,这些方法具有显式传递的C++this参数。此外,一些结构是由指向一个特别选择的元素的指针定义的,该元素保存在方法的全局范围中。

因此,当你想传递整个结构,例如一棵树,并且需要更改根或列表的第一个元素时,你可以将一个指针对指针传递给这个特殊的root/head元素,这样你就可以更改它

注意:这是c风格的实现,使用c++语法以方便使用。

void add_element_to_list(List** list, Data element){
Data new_el = new Data(element); // this would be malloc and struct copy
*list = new_el; //move the address of list, so it begins at new element
}

在c++中有引用机制,通常你可以用它实现几乎任何东西。它基本上使指针的使用过时了。至少在很多情况下是这样。你也可以设计和处理对象,所有的东西都隐藏在这两个引擎盖下。

最近还有一个很好的问题"为什么我们在c++中使用指针?"或者类似的问题。

一个简单的例子是矩阵的实现(这是一个例子,不是用C++实现矩阵的最佳方式)。

int nrows = 10;
int ncols = 15;
double** M = new double*[nrows];
for(unsigned long int i = 0; i < nrows; ++i)
M[i] = new double[ncols];
M[3][7] = 3.1416;

您很少在普通C++代码中看到这种构造,因为C++有引用。它在C中用于"通过引用传递:">

int allocate_something(void **p)
{
*p = malloc(whatever);
if (*p)
return 1;
else
return 0;
}

等效的C++代码将使用void *&p作为参数。

尽管如此,你仍然可以想象这样的资源监视器:

struct Resource;
struct Holder
{
Resource *res;
};
struct Monitor
{
Resource **res;
void monitor(const Holder &h) { res = &h.res; }
Resource& getResource() const { return **res; }
}

是的,这是人为的,但想法就在那里——它会将指向指针的指针存储在持有者中,即使持有者的res指针发生变化,也会正确返回该资源。

当然,这是一个悬而未决的取消引用等待发生——通常,你会避免这样的代码。