我正在查看实现堆栈的链表的教科书示例。我不明白为什么使用指向堆栈的指针是推送操作所必需的。请参阅以下示例:
bool push( Element **stack, void *data)
{
Element *elem = new Element;
if(!elem) return false;
elem->data = data;
elem->next = *stack;
*stack = elem;
return true;
}
如果有人可以帮助澄清为什么push方法的第一个参数是指向指针的指针,我将非常感激。感谢。
太棒了,谢谢你提供的所有帮助。
答案 0 :(得分:8)
该函数需要修改Element指针的值,因此它需要一个指向 指针的指针。
换句话说:当一个函数需要修改那个东西时,它会获取一个指针。
在这种情况下,某事物本身就是指针。因此该函数最终会获取指向指针的指针。
答案 1 :(得分:4)
指针只是一个包含值的变量,该值是一个内存地址。
指向指针的指针也只是一个保存值的变量。该值是指针的内存地址。
当您想要更改指针的值时,可以使用指针指针。
//Not a very useful example, but shows what I mean...
void getOffsetBy3Pointer(const char *pInput, char **pOutput)
{
*pOutput = pInput + 3;
}
你这样称呼这个函数:
const char *p = "hi you";
char *pYou;
getOffsetBy3Pointer(p, &pYou);
assert(!stricmp(pYou, "you"));
现在考虑如果我们尝试使用单个指针实现此功能会发生什么。
//Note: This is completely wrong
void BadGetOffsetBy3Pointer(const char *pInput, char *pOutput)
{
//*pOutput refers to the first actual char element that pOutput points to.
pOutput = pInput + 3;
//pOutput now points to pInput + 3, but the variable we passed in remains distinct.
}
你这样称呼这个函数:
const char *p = "hi you";
char *pYou = NULL;
BadGetOffsetBy3Pointer(p, pYou);
assert(pYou == NULL);
请注意,在BadGetOffsetBy3Pointer中,我们可以更改一些字符,但我们无法更改pYou指向的内容。
答案 2 :(得分:1)
堆栈基本上是指针的链接列表。每个指向它下面的一个。 因为您有一个新元素,并且您希望该元素在列表中排在第一位(因此称为“堆栈”,您必须更改指向列表开头的内容。
要更改“指向列表头部的指针”中的值,您需要该地址 指针。
答案 3 :(得分:1)
由于这一行:
*stack = elem;
基本上你正在修改函数内的原始指针。
答案 4 :(得分:0)
您必须更新指针。
列表只是指向Element
的指针。
所以你可以将其重写为
bool push(List* stack, void* data);
不是你看到的,如果你不使用双指针,你的实际声明是
bool push(List stack, void* data);
根本不会改变原始列表。
但另类,
bool push(Element* &stack, ...)
也可以,因为它允许您更新。
答案 5 :(得分:0)
堆栈由指向最后一个元素的指针表示。为了通过将元素推到它上来更改堆栈,必须更新此指针,因此我们将指针传递给push函数。
答案 6 :(得分:0)
看看有人会如何使用这个推送功能:
Data d1, d2;
Stack *s = null; // s := null
push(&s, &d1); // s := {d1}->null
push(&s, &d2); // s:= {d2}->{d1}->null
现在你可以继续使用变量s,它已被push修改为指向不断增长的堆栈顶部。
在堆栈中,你总是希望保持一个指向顶部的指针,而push函数可以更容易地维护这个指针。