C++ 引用及其与指针的区别

时间:2021-03-13 20:01:30

定义,嘛是引用?说的直白一点,引用就是对象的别名,这玩意最好的例子就是:假如你爹姓大,为了你以后闯荡江湖,你读书的时候要起个学名叫大狗剩,但你也有小名(某些文雅的人士叫乳名)叫狗剩,村里人都喊你狗剩,于是狗剩就是你的别名,你回家看看你的户口本,上面只写着大狗剩,此处就相当于内存,狗剩这个别名不占用空间,但是和大狗剩一样,都是指的你。

特点:先来看看跟指针的区别
      1 引用访问一个变量是直接访问,而指针是间接访问。
  2引用是一个变量的别名,本身不单独分配自己的内存空间,指针有自己的内存空间。
  3引用在开始的时候就绑定到了一个内存空间(开始必须赋初值),所以他只能是这个
  内存空间的名字,而不能改成其他的

(以下程序可能会因为word原因出现大小写问题比如“int”变成“Int”,知道就好了,敬请谅解)

(一)来一条一条看,先来看“别名”,别名的意思就是是一个东西,

           int value; 

          int & refValue= value;

现在refValue就是value的一个引用,上面代码体现了两处,一是引用的定义,其次是定义引用的时候需要立即初始化,定义引用跟指针差不多,类型后面跟个&,不要跟取地址混了,

所谓立即初始化就是马上!,

所以你不能这样写:

int & refValue;

refValue= value;

另外与此沾边的是在任何情况下都不能使用空值的引用,你不能让他什么都不引啊,于是乎有些操蛋的家伙可能想到写这样的代码:

Int * ptrValue=NULL;

Int &refValue=(* ptrValue);

拖出去阉了吧,这样的代码应该避免,结果不确定,会很有害。

(二)引用是直接访问变量,指针是间接,所谓间接就是指针指向变量地址,需要使用“*”(解引用运算符)

   说的明白一点就是直接用呗,跟原变量名一样直接用,不用添加额外的符号,但产生的是按引用的效果(比如按引用传值)

        比如:

             Int preValue=1

             Int realValue=2

       Void changeValueint &aint&b

{

              Int temp=a

               a=b;

               b=a; 

}

现在调用函数:changeValuepreValuerealValue);

注意preValuerealValue不需要加&,调用后preValue的值为2realValue的值为1,这就是传说中的按引用传值,碉堡了。

(三)忠贞不二,引用只能被绑定一次,不能再引用别的变量,跟指针个这狗日的不一样,

比如对于指针,int value=1; 

              int fuckValue=2

int *preValue=&value

现在preValue指向value

preValue=&fuckValue

现在preValue指向fuckValue了,你执行*preValue=6;它改变的是fuckValue的值。

         但对于引用‘

  int value=1; 

           int fuckValue=2

int & refValue= value;

现在refValuevalue的引用。

假如你执行refValue= fuckValue

此时refValue也不会变成fuckValue的引用,而只是会改变value的值为2

现在再来看看引用的另外两个特点

(一),如果一个函数返回的是一个引用类型,那么该函数可以被当作左值使用,当作左值的简单理解就是可以被赋值,比如

            函数声明为:int & changeValue(int i);

            在程序中:

                     Int value=1

                     Int fuckValue=2

                     changeValuevalue= fuckValue

这样是正确的,至于changeValue的内部实现可能有多种情况,具体结果,要看return什么玩意了。

借花献佛,举个别人的例子:       

 int i; 
                 int& f1(int&i) 
                 { 
                    return i; 
                 } 
    
                f1(i)=3;这跟i=3效果是一样的。

(二)引用的转换

  假如        float f; 
                int &rv=f;

加国是这种引用转换不能通过编译,但是并不是所有的转换都不能进行,比如基类就可以被作为派生类的引用(字面理解相当于将派生类转换成基类)

注意需满足两个条件:1,指定的基类是可访问的。2,转换是无二义性的

借花献佛举个例子:

class A 
           { 
             public: 
                 int a; 
           }; 
           class B:public A 
           { 
            public: 
                 int b; 
           }; 

A Oa; 
           B Ob; 
           A& mm=Ob; 
           mm.a=3; 

最后,别人总结了一下,我觉得挺好,拿来用了

1。对象和对象的引用在某种意义上是一个东西,访问对象和访问对象的引用其实访问的是同一块内存区。 
2。使用对象和使用对象的引用在语法格式上是一样的。 
3。引用必须初始化。 
4。引用在初始化中被绑定到某个对象上后,将只能永远绑定这个对象。 
5。基类类型的引用可以被绑定到该基类的派生类对象,只要基类和派生类满足上文提到的两个条件(1,指定的基类是可访问的。2,转换是无二义性的) 。这时,该引用其实是派生类对象中的基类子对象的引用。
6。用传递引用的方式给函数传递一个对象的引用时,只传递了该对象的地址,系统消耗较小。在函数体内访问     形参,实际是访问了这个作为实参的对象。 
7。一个函数如果返回引用,那么函数调用表达式可以作为左值。