背景:

最近刚开始自学数据结构,大学学的实在是云里雾里的,想着自己用C++实现一下伪代码吧,大概思路是这样的:

在main里定义了一个SqList *L = NULL;

在InitList(SqList *L);函数里new出来一块内存分配给L:

  L = new SqList();

因为L是在main里定义的,按照我所预想的,在初始化函数里分配了内存块就OK了,因为指针传参传递的是地址,所以L肯定被改变了。

但是事实是,一旦退出了InitList之后,L的地址就回归到了坑爹的全0


我通过指针传递参数,并试图在函数体内改变指针,但是发现这只是改变了函数体内的指针,函数结束后,main里的指针还是任尔东南西北风我自岿然不动j_0016.gif


一、 你所传递和改变的到底是什么

为什么会这样呢?明明我以前做指针传参的话,值都改变了啊(你大概会这么想)

废话不多说,百思不得其解的时候可以通过一个小demo测试一下


#include <iostream>
using namespace std;
void changePointer(int *p)
{
    p = new int(1);
    cout << "p in = " << p << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    changePointer(p);
    cout << "p2 = " << p << endl;
    return 0;
}

这个结果很坑爹的验证了之前的问题:

wKiom1NTg4DwyVSIAAAnFyBKUYE850.jpg

看到没有?

p在经过changePointer之后并没有改变其地址,问题就在这里:

我们平常是用指针传递参数,然后在函数体里改变指针保存的地址所存储的值,而不是改变指针所保存的地址,这里很多人都会偷换了概念

好吧,有一点绕口,上代码,仔细考虑一下以下两行代码的区别:

*p = 1; // p并没有被改变,但是p所指向的值被改变了
p = new int(1); // p被改变了


是不是不一样?好了,知道了为什么这个跟平时自己用的指针传参不一样之后,让我们考虑一下,是什么导致了p在函数体内被改变了,出了函数体就变回来了呢?


二、指针参数究竟是如何传递的

记得之前看过一个关于参数传递的文章,具体的不记得,大概有临时变量这么一说,既然是临时的,会不会出函数就over了,所以就导致了main中的p未被改变?

记忆总是模糊的,我们可以问度娘

事实证明确实是这样的

问过度娘之后,得到这么一句话:

编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因

而如果我们修改的是_p保存的地址,而非_p地址指向的值,那么函数结束之后,临时变量被修改和p有毛关系呢


三、怎么样才能达到我们的预期目的——改变指针


1. 比较简单的一种是:返回值

直接把在函数体里new出来的返回就好了嘛~~~

检验一下:

int* changePointer(int *p)
{
    p = new int(1);
    cout << "p in = " << p << endl;
    return p;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    p = changePointer(p);
    cout << "p2 = " << p << endl;
    return 0;
}

输出:

wKiom1NTgAPyhDTJAAAiIhVKHzo202.jpg

Good job~!你妹的指针终于被改了有木有~~~


2. 指针的指针

void changePointer(int **p)
{
    *p = new int(1);
    cout << "p in = " << *p << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int *p =new int(0);
    cout << "p1 = " << p << endl;
    changePointer(&p);    // 注意这里传递的是&p
    cout << "p2 = " << p << endl;
    return 0;
}

输出:

wKioL1NTgOHw1cXlAAAicBKdoA4394.jpg


作为一个渣渣,C++慢慢抠语法抠底层真的很辛苦,成为大神之路任重而道远

干吧呆,小伙伴们