指针和指针的指针的理解问题
下面是两个创建链表的函数代码
void AddToTail(ListNode *pHead, int val)
{
ListNode *pNew = new ListNode();
pNew->m_nValue = val;
pNew->m_pNext = NULL;
if(pHead == NULL)
{
pHead = pNew;
}
else
{
ListNode *pNode = pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
}
}
void AddToTailEx(ListNode **pHead, int val)
{
ListNode *pNew = new ListNode();
pNew->m_nValue = val;
pNew->m_pNext = NULL;
if(*pHead == NULL)
{
*pHead = pNew;
}
else
{
ListNode *pNode = *pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
}
}
不同之处在于第一个参数 AddToTail的第一个参数是个指针,AddToTailEx的第一个参数是指针的指针,
AddToTail函数返回后,链表节点为空 第二个函数AddToTailEx没有问题。
我不太理解的是为什么第一个函数在执行完后变成空了?是因为pNew被收回了吗?
那为什么第二个函数没有出现这个问题?pNew不是也在函数返回的时候收回了吗?
第二个函数中*pHead = pNew;该怎么理解才好?
[解决办法]
当你想把一个地址值作为输出参数带出函数之外,你就需要这个地址值的地址
pNew没有被回收,第一种方式会内存泄露
ListNode *pHeadOut = NULL;//pHeadOut的地址比如0x1234
AddToTail(pHeadOut , 0);这样用
此时的外面的pHeadOut 和 你进入AddToTail时的那个参数pHead 是两个不同的变量
参数pHead的地址有可能比如说是0x5678
AddToTail里面执行pHead = pNew;
意思就是在地址0x5678上存储pNew,而不是存在0x1234上
所以赋值给参数pHead,而不是AddToTail外面的那个pHeadOut
AddToTail(&pHeadOut , 0);这样用
是将pHeadOut的地址给了AddToTail的那个参数pHead,
就是说pHead里面存的是0x1234
就是说此时的参数pHead是你pHeadOut的地址,
*pHead就是地址0x1234里面存的值(一开始是空,就是ListNode *pHeadOut = NULL;赋值的NULL)
AddToTail里面执行*pHead = pNew;就是对0x1234这个地址赋值pNew,就是把pNew给了0x1234这个地址的那个变量 就是pHeadOut
[解决办法]
理解指针的指针,就是将指针本身当作一个变量理解,
指针的指针就是这个变量的地址。
另外
void AddToTail(ListNode *pHead, int val)
//这个改为下面的好点,
void AddToTail(ListNode *pHead, int val)
{
if(pHead == NULL) return;
ListNode *pNew = new ListNode();
pNew->m_nValue = val;
pNew->m_pNext = NULL;
{
ListNode *pNode = pHead;
while(pNode->m_pNext != NULL)
pNode = pNode->m_pNext;
pNode->m_pNext = pNew;
}
}