• C++指针、引用知多少?


     

           上午搞了一个小程序,test半天都没有得到想要的结构,原来是递归的时候没有注意的循环的问题,结果直接死循环了。催了...看来当程序出现问题的时候,首先要整理的是算法思路是否有问题,其次是算法的实现,是否容易进入死循环,边界条件是否出现错误。

           好的,废话不多说,继续整理。

           指针

           指针这东西,要是搞复杂了,这还真是高深莫测,你不认真研读研读还真不行,真心觉得搞程序一浮躁,各种bug就都出来了。

           指针的声明:

    复制代码
    1     int x=20;
    2     int *p,q;
    3     int* m,n;
    4     p=&x;
    5     q=x;
    6     m=&x;
    7     n=x;
    8     cout<<*p<<" "<<q<<" "<<*m<<" "<<n;
    复制代码

         我想,这应该就是最简单的声明了吧,p是一个指针,并且是一个指向x的指针。那么如果cout<<p;会得到什么结构呢?其实p本身保存的是一个地址。并且保存的是x所存储的地址。

       不信的话可以改成以下语句:

    复制代码
    1     int x=20;
    2     int *p,q;
    3     int* m,n;
    4     p=&x;
    5     q=x;
    6     m=&x;
    7     n=x;
    8     cout<<p<<" "<<&x<<" "<<m;
    复制代码

       他的输出结果就是:

      

       所以,在这里我们已经对指针有一个初步的认识,指针其实就是一个地址的东西,只不过这个地址保存的是我们所指向的值得地址。

       空指针void*

       我们一般的指明了指向类型的指针都是只能指向该类型的,比如说上面提到的p指针,它只能指向Int类型。但是void*是怎么样的呢?

       其实void*指针可以指向任何类型,当然也可以指向int。如果我们下面代码会出现什么情况呢?

    1     void *y;
    2     y=&x;
    3     cout<<y;

       实际上我们会发现,y输出的是地址,并且和上面的P,m的地址是一致的,实验发现,我上面的说法是对的。

       很显然,如果仅仅得到一个void*指针是没有太大意义的,那么我们怎么把他转化成原有的int*,甚至转化成int呢?

       这里我们需要显示转化,(int*)y,转化成整数的话就是*((int*)y);

       所以现在我们应该知道了当函数的返回值是void和void*是有多么大的不同了吧。void*是返回一个特殊的指针类型。

       多重指针

       这里说的多重指针在很多地方也称为指向指针的指针。

       我们是不是经常会遇到int **m;这种情况呢,其实他就是一个多重指针。

       还是上面那个例子,我们以下定义一个多重指针

    1     int **z;
    2     z=&p;
    3     cout<<"多重指针"<<p<<*z;

       p我们知道会输出x的地址,那么*z又是上面呢,z是一个指向指针p的指针。那么z保存的是p的地址,*z理所当然的应该保存的也是x的地址。见下图

       了解了这个之后,那么我们就很容易的知道了,动态二维数组的创建过程了,就是一个指向指针的指针,二重指针嘛,so easy。

       函数指针

       我们经常会需要动态的调动几个函数的某一个,如果我们只是if else那代码量可能有时候会比较大,有没有可以在函数参数中直接传递一个函数呢?

       答案是不可能的,但是我们有一种方式可以实现,那就是通过指针函数来说。

       typedef void (*pf)(int &m,int *n);

       这是什么意思呢?他的意思就是说pf是一个指针函数,他可以指向任意的返回值为void,并且参数是int &m和int *n的函数。

        同样我们声明pf f;就可以把f作为一个函数了,也可以把f当做一个参数传到函数体中了。具体例子见下面。

    复制代码
     1 void swap(int &m,int *n); //定义一个有两个参数的函数swap
     2 typedef void (*pf)(int &m,int *n);//
     3 void print(int &m,int *n,pf x);//定义一个能传递指针函数的函数
     4 int _tmain(int argc, _TCHAR* argv[])
     5 {
     6     int m=6,q=20;
     7     pf f=swap;
     8     int* n=&q;
     9     f(m,n);
    10     cout<<&m<<*n;
    11     print(m,n,f);
    12     system("pause");
    13     return 0;
    14 }
    复制代码

        同样的道理,我们也可以返回一个指针函数,只不过返回类型是pf。它返回的实际类型应该是 void (*)(int&,int*);解释起来就是一个指向两个传输的函数指针。

       我们可以定义一个 pf fun();他就返回的是函数指针了。

        引用&

        实际上引用能起到的作用,*很多时候也能够起到,那为什么我们还经常说,要尽量使用引用呢?最大的优点就是指针更安全。当然某些情况下例外。

        引用可以认为是一个别名,而指针则是一个实体,虽然他们都有地址的概念在里面。

        这里主要描述一下引用和指针的不同之处。

         1、指针是可以重新指向另外一个对象,而引用不行,引用一旦绑定那就不能再绑定其他了,引用的这种性质有一点嫁鸡随鸡嫁狗随狗的意味在里面。这对男人是不是更安全呢?O(∩_∩)O哈哈~

         2、指针可以是空指针,但是引用不能是空引用啊,所以引用都是必须初始化的。

         3、指针是指向一个实体(程序为指针变量分配内存区域),而指针则是一个别名,这个可以怎么理解呢?我们通过sizeof(指针)和sizeof(引用)可以知道,前者是指针的大小,一般为4,而后者则是引用对象的大小,也就是说,如果对一个字符串长度为100的字符串进行引用sizeof是100哦,而指针还是4.

        4、如果需要返回动态分配的对象或者内存,应该使用指针,引用很有可能引起内存泄露问题。

        当然还有其他的一些不同,但是总体来说都是由以上衍生出来的。

        其实引用本质上来说是一种指针,只不过编译器进行了优化(所以指针更加灵活),所以引用具有指针的特点,又更安全。

     

     

      转载请注明出处:http://www.cnblogs.com/xiaoyi115/p/3625296.html

  • 相关阅读:
    【Luogu】P3809后缀排序(后缀数组模板)
    【Luogu】P2709小B的询问(莫队算法)
    【Luogu】P2766最长不下降子序列问题(暴力网络流)
    【Luogu】P2486染色(树链剖分)
    【bzoj】P4407于神之怒加强版(莫比乌斯反演)
    【Luogu】P3343地震后的幻想乡(对积分概率进行DP)
    【Luogu】P2146软件包管理器(树链剖分)
    【Luogu】P3159交换棋子(超出我能力范围的费用流)
    【Luogu】P2569股票交易(单调队列优化DP)
    【Luogu】P2219修筑绿化带(单调队列)
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/3642463.html
Copyright © 2020-2023  润新知