走进C++程序世界-------浅谈引用

什么引用:

    引用是别名,创建引用时,将其初始化另外一个对象,引用(reference)是C++对C语言的重要扩充。引用的声明的方法:类型标示符 & 引用名 = 目标变量名;说明:
   1、&在此不是求地址运算,而是其标识作用。
    2、类型标示符是指目标变量的类型。
    3、声明引用时必须对此进行初始化。
    4、引用声明完毕后,相当于目标变量名优两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量的别名。
    5、声明一个引用,不是新定义了一个变量,它只是表示该引用名师目标变量名的一个别名,他本身不是一个数据类型,因此引用本身不占有存储单元,系统不给引用分配存储单元。因此对引用求地址就是对变量名求地址
    6、不能建立引用的数组,因为数组是一个由若干个元素所组成的集合,所以无法建立一个由引用组成的集合。但是可以建立数组的引用。(目前有点绕,不太理解。所以最好引用不要操作数组)下面是关于这条的例子:
 int& ref [3]= {2,3,5};//声明ref引用的数组错误
但是可以这样写:
const int (&ref)[3] ={2,3,5}; //gcc编译的时候加上选项 -std=c++0x
ref[0] = 35;                          //错误
为什么要加上const ,因为{2,3,5}此时是个字面值数组,是保存在代码段里,只读的属性,如果不加,编译错误,而且后面对ref[0]的赋值也不会成功.
    下面是在代码中对上面说明进行验证上面的5条:
/*
 *reference.cpp
 *Date : 2013-9-19
 *Author: sjin
 *Mail:413977243@qq.com
 */

#include <iostream>
using namespace std;

int main()
{
    int intone;
#if 1
    int &rSomeRef = intone;//引用必须初始化
#else
    int &rSomeRef;
    rSomeRef = intone;
    /*如果执行这里会报下面的错误,可以自己尝试下
     * reference.cpp:17: error: ‘rSomeRef’ declared as reference but not
     * initialized
     */
#endif
    intone = 5;
    cout << "intone :\t" << intone <<"\t\t rSomeRef :\t" << rSomeRef << endl;
    cout << "&intone :\t" << &intone <<"\t rSomeRef :\t" << &rSomeRef << endl;
    
    rSomeRef = 10;
    cout << "intone :\t" << intone <<"\t\t rSomeRef :\t" << rSomeRef << endl;
    cout << "&intone :\t" << &intone <<"\t rSomeRef :\t" << &rSomeRef << endl;

    /*这个在很多书籍上都强调不要对引用重新赋值。
     * 给引用重新赋值相当于给目标重新赋值。
     * 引用的地址还是和目标变量的地址一致
     */
    cout << "*******************引用重新赋值后*******************" << endl;
    int inttwo = 50;
    rSomeRef = inttwo;
    cout << "intone :\t" << intone <<"\t\t rSomeRef :\t" << rSomeRef << endl;
    cout << "&intone :\t" << &intone <<"\t rSomeRef :\t" << &rSomeRef << endl;
    cout << "inttwo :\t" << inttwo <<"\t\t rSomeRef :\t" << rSomeRef << endl;
    cout << "&inttwo :\t" << &inttwo <<"\t rSomeRef :\t" << &rSomeRef << endl;
    cout << "*****************************************************" << endl;
    return 0;
}

输出:
intone :	5		 rSomeRef :	5
&intone :	0xbfb6c2d8	 rSomeRef :	0xbfb6c2d8
intone :	10		 rSomeRef :	10
&intone :	0xbfb6c2d8	 rSomeRef :	0xbfb6c2d8
*******************引用重新赋值后*******************
intone :	50		 rSomeRef :	50
&intone :	0xbfb6c2d8	 rSomeRef :	0xbfb6c2d8
inttwo :	50		 rSomeRef :	50
&inttwo :	0xbfb6c2d4	 rSomeRef :	0xbfb6c2d8
*****************************************************

空指针和空引用

在指针没有被初始化和删除指针时,应将它们赋为空。但引用并非如此,因为必须在创建时同时将引用初始化为它指向的东西。

使用引用来实现swap()函数

 
/*
 *swap.cpp
 *Date : 2013-9-20
 *Author: sjin
 *Mail:413977243@qq.com
 */
#include <iostream>
#define N 0
using namespace std;
void swap2(int *x,int *y)
{
    int temp;
    cout << "*******************swap2(传递地址)************************" << endl;
    cout << "before swap x :" << x <<"\t y :"<<y <<endl;
    cout << "before swap &x :" << &x <<"\t &y :"<< &y <<endl;
    temp = *x;
    *x = *y;
    *y = temp;
    cout << "after swap x :" << x <<"\t y :"<<y <<endl;
    cout << "after swap &x :" << &x <<"\t &y :"<< &y <<endl;
    cout << "*******************swap2(传递地址)************************" << endl;

}
#if N
void swap(int &x, int &y)
#else
void swap(int x, int y)
#endif
{
    int temp;
    cout << "*******************swap()************************" << endl;
    if(N == 1){
        cout << "引用实现数据交换" << endl;
    }else{
        cout << "普通实现数据交换(错误的数据交换)"<<endl;
    }
    cout << "before swap &x :" << &x <<"\t &y :"<<&y <<endl;
    temp = x;
    x = y;
    y = temp;
    cout << "after swap &x :" << &x <<"\t &y :"<<&y <<endl;
    cout << "*******************swap()************************" << endl;
    
}
int main()
{
    int x = 5, y = 10;
    cout << "验证引用下数据交换" << endl;
    cout << "before swap, x: "<< x << "\t y: " << y << endl;
    cout << "before swap, &x: "<< &x << "\t &y: " << &y << endl;
   // swap(x,y);
    swap2(&x,&y);/*使用指针传递*/
    cout << "after swap, x: "<< x << "\t y: " << y << endl;
    cout << "after swap, &x: "<< &x << "\t &y: " << &y << endl;
    return 0;
}

输出结果:

当N为 1时:引用传递/

验证引用下数据交换
before swap, x: 5	 y: 10
before swap, &x: 0xbfc5a09c	 &y: 0xbfc5a098
*******************swap()************************
引用实现数据交换
before swap &x :0xbfc5a09c	 &y :0xbfc5a098
after swap &x :0xbfc5a09c	 &y :0xbfc5a098
*******************swap()************************
after swap, x: 10	 y: 5
after swap, &x: 0xbfc5a09c	 &y: 0xbfc5a098

当N为0时:按值传递

验证引用下数据交换
before swap, x: 5	 y: 10
before swap, &x: 0xbff4eaec	 &y: 0xbff4eae8
*******************swap()************************
普通实现数据交换(错误的数据交换按值传递)
before swap &x :0xbff4ead0	 &y :0xbff4ead4
after swap &x :0xbff4ead0	 &y :0xbff4ead4
*******************swap()************************
after swap, x: 5	 y: 10
after swap, &x: 0xbff4eaec	 &y: 0xbff4eae8

swap2()按地址传递

验证引用下数据交换
before swap, x: 5	 y: 10
before swap, &x: 0xbfd793ec	 &y: 0xbfd793e8
*******************swap2(传递地址)************************
before swap x :0xbfd793ec	 y :0xbfd793e8
before swap &x :0xbfd793d0	 &y :0xbfd793d4
after swap x :0xbfd793ec	 y :0xbfd793e8
after swap &x :0xbfd793d0	 &y :0xbfd793d4
*******************swap2(传递地址)************************
after swap, x: 10	 y: 5
after swap, &x: 0xbfd793ec	 &y: 0xbfd793e8


透过上面的输出结果,我们很容易看到3种方法在数据交换中情况。很明显看到引用传递的优越性,不需要在堆栈中创建临时副本来保存数据。也就是说按引用传递可以提高效率,减少内存的开销。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值