详解指针的指针

int i = 5, j = 6, k = 7;

int *ip1 = &i, *ip2 = &j;

int **ipp = &ip1;
那么现在指针 ipp 指向了 ip1,ip1 指向了 i。*ipp 就是 ip1,**ipp 就是 i,或者说是 5。我们可以用我们熟悉的盒子箭头图来描述,像这样:

*ipp = ip2;

我们就改变了 ipp 指向的那个指针(也就是 ip1),现在它指向 ip2 所指的地方。也就是说(ip1)现在它指向了 j:

& 符号的意思是取地址,也就是返回一个对象在内存中的地址。

* 符号的意思是取得一个指针所指向的对象。 也就是如果一个指针保存着一个内存地址,那么它就返回在那个地址的对象。

所以当你这么写时 *ipp = ip2,实际上是把 ipp 存的地址所对应的对象,也就是 ip1 取到,然后把 ip2 存的值赋值给 ip1,也就是 j 的地址。

 
int m_value = 1;

void func(int *p)
{
    p = &m_value;
}

int main(int argc, char *argv[])
{
    int n = 2;
    int *pn = &n;
    cout << *pn << endl;
    func(pn);
    cout << *pn <<endl;
    return 0;
}

输出值为2 2

当我们把一个指针做为参数传一个方法时,其实是把指针的复本传递给了方法,也可以说传递指针是指针的值传递。如果我们在方法内部修改指针会出现问题,在方法里做修改只是修改的指针的copy而不是指针本身,原来的指针还保留着原来的值。

void func(int **p)
{
    *p = &m_value;

    // 也可以根据你的需求分配内存
    *p = new int;
    **p = 5;
}

int main(int argc, char *argv[])
{
    int n = 2;
    int *pn = &n;
    cout << *pn << endl;
    func(&pn);
    cout << *pn <<endl;
    return 0;
}

输出值为2 5

p:  是一个指针的指针,在这里我们不会去对它做修改,否则会丢失这个指针指向的指针地址

*p:  是被指向的指针,是一个地址。如果我们修改它,修改的是被指向的指针的内容。换句话说,我们修改的是main()方法里 *pn指针,分配了新的内存空间。

**p: 两次解引用是指向main()方法里*pn的内容

int m_value = 1;

void func(int *&p)
{
    p = &m_value;

    // 也可以根据你的需求分配内存
    p = new int;
    *p = 5;
}

int main(int argc, char *argv[])
{
    int n = 2;
    int *pn = &n;
    cout << *pn << endl;
    func(pn);
    cout << *pn <<endl;
    return 0;
}

输出值为2 5

p:  是指针的引用,main()方法里的 *pn

*p:是main()方法里的pn指向的内容。

原文地址:https://www.cnblogs.com/home123/p/7368528.html