回 帖 发 新 帖 刷新版面

主题:[原创]C++第五讲―――引用

                             C++第五讲―――引用



    地球上有一种古老的文化,叫做绰号,东方的文化在这里有有良好的记载,以《水浒传》为甚。提起黑旋风,我们就想起李逵;提起豹子头,我们就想到了林冲;呵呵,在往前数数,国人之师孔子字仲尼;近代呢,我们近代思想的巨人(新文化运动的导师)陈独秀先生字仲甫。

    计算机的对象(从前我们叫做变量)代表现实社会中的事物,那他们可以有绰号吗?关键是看编译器有这项规定否?在C语言的编译器里面,是有的。编译器给它起了一个好听的名字―――引用(呵呵,历史有点鬼)。也就是变量的绰号。世上的文化有惊人的相似性,计算机和人类都有共同的文化,我把它叫做绰号文化。

    那么为什么要出现绰号呢?计算机出现了绰号有什么好处呢?一个人的绰号,代表了一个人某个方面的很形象特征。方便了人类的记忆。计算机的引用正好相反。多了一个变量,程序变量的可控性变弱了。但他有这样的好处。两个变量代表一个事物,具有广泛的代表性,可以使用在多个地方,操作的是同样的内容,也就是灵活了。

    如果我们有了一个变量i,那么我们怎么样的声明该变量i的引用j呢,程序如下:
    int   i=2008;
int  &j=i;   //怎么能这样写呢,呵呵,这是怎么了。

看到这一点之后,又有一点迷茫。是书写格式的迷茫,怎么能这样写呢???思想提出抗议了。从前学习过指针,&符号是取地址的,在这里&代表的涵义是什么呢???

解释:在这里面&没有地址的涵义,仅仅格式而已!!!!如果最开始编译器把没有用&,用$,那今天广大的程序员就用$了。在这里,仅仅是符号,没有地址的涵义,是为了编译器编译的时间的确认。当编译器在看到这样的定义,int &i,马上明白了,说这是后面(  =i   )的绰号吧,然后编译器就把i的地址给了j,j也就是i了。

我们不能一看到&就想起了指针,想到地址的涵义。这是错误的,纵然引用是共享内存空间,但是它和我们前面讲述的指针的逻辑是不一样的。举个例子吧:就像某某人穿了日本军旗装,惹得爱国青年一片臭骂,就把她和某某联系在一起了。其实从本质而言,我认为她在穿军旗装的时间,未必想到自己就被大家认为是日本人了,标新立异是演员的心理吗,整天想着怎么抢夺观众的眼球呀。呵呵(如果你不同意这样的观点,不要骂我呀,算我说错了)。如果你在学习的时间总拿着前面指针的逻辑,那就钻了牛角尖了。和前面的爱国青年一样了,也会冲动的。

结论:两个变量指向同一块内存空间,是引用的本质涵义。明白了吗?^_^。

    实例:
void main()
{
    int i=2008;//变量i的引用
    int &j=i;//变量j是变量i的引用,他们共享了内存
    printf("%d\n",i);//一个地址空间,当然存储数值一样了
    printf("%d\n",j);
    printf("%d\n",&i);//一个地址空间,所以打印是相等的
    printf("%d\n",&j);
    i=3008;              
    printf("%d\n",j);  //对原变量的改变也就是对指针变量的改变
    j=4008;   
    printf("%d\n",i);   //对指针变量的改变也就是对原变量的改变
}
结果:
2008
2008
1245052
1245052
3008
4008

    请注意:如果b是a的引用,那么b就不能是c的引用了,只能引用一次,也就是一个绰号只能供一块内存使用。不能2个人公用一个绰号吧。

    如果b是a的引用,那么b就不能够解除与a的引用关系(这个不大肯定,我还没有看过书上讲述怎么去掉变量的引用呢,如果我发现了,我在告诉你)。就象一个人有了绰号,很难改变一样。

    
    引用的一个重要的用途是在函数参数里面。
函数就是一个加工单位。举例:假如你有1000万(这个数目大吗?年轻人要敢想象呀!!!),从建行转到中行。那么我们怎么把钱送到银行呢?

思索之后,有如下几种方式:
第一:派人护送,用保险箱把取出的钱拉过去。把钱从建行拉到中行,属于传值问题。

第二:让中行来人,处理钱。你给中行一个地址,中行派人来处理钱,属于传地址问题。

第三:转过去个支票。不从建行取钱,你开出一个支票。把这个支票给中行就可以了。


呵呵,杀猪杀尾巴,各有各的杀法。

第一和第二,第三种的区别:第一属于传数值,第二,第三属于传地址。在计算机里面,从一个地方把数据拷贝到另外一个地方是非常耗费计算机资源的。所以第一种方法效率最低。

第二和第三种的相同点:都是属于传地址的问题。

第二和第三种方式的区别:第二种方式在传递地址时,编译器要给保存地址的指针变量开辟空间,故多占用了一块内存。而引用不需要开辟空间。引用共享内存的涵义就是少了指针变量开辟的空间。少了一个地址的中转,少了地址的传递。故第三种效率更高。

看如下程序:
//为什么声明3个变量呢,代表着3种转帐方式,方便理解,oldMoney代表你从前的钱数

int oldMoney1=2000;//你从前的2000万钱
int oldMoney2=2000;
int oldMoney3=2000;

//三个转帐函数,对应3种不同的转帐过程。

int ZhuanZhang1(int tempMoney)//第一种,传值
{
    return oldMoney1+tempMoney;
}

int ZhuanZhang2(int *tempMoney)//第二种方式:开辟一个指针变量
{
    return oldMoney2+*tempMoney;
}

int ZhuanZhang3(int &tempMoney)//第三种方式:把自己的地址直接传过去,不在经过指针变量的中转。
{
    return oldMoney3+tempMoney;
}

void main()
{
    int newMoney=1000;//你要中转的1000万钱

    // nowMoney代表转帐后你的钱的数目
    int nowMoney1=ZhuanZhang1(newMoney);
    int nowMoney2=ZhuanZhang2(&newMoney);
    int nowMoney3=ZhuanZhang3(newMoney);

    printf("%d\n",nowMoney1);
    printf("%d\n",nowMoney2);
    printf("%d\n",nowMoney3);
}
结果:
3000
3000
3000
    本程序读者一定要多加揣摩。夜深人静,孤灯冷月之时还望读者多加思索。

    引用纵然效率最高,但是也有缺点。直接传递变量本身。我们写程序可以保证变量本身我们不去改变它,但如果该变量的引用修改了,变量本身也就改变了。那怎么办呢???我们考虑到了C语言里面的一个修饰符号,那就是const。呵呵,这个东西还是很有用的,用它限定引用好了,用它以修饰,就不能改变引用了。那么变量本身也就安全了,引用其实在很多地方和const是在搭配使用的。MFC里面的函数参数是引用的地方几乎都少不了const。看如下程序:

int ZhuanZhang3(int &tempMoney)//第三种方式:把自己的地址传过去,不在经过指针变量的中转。
{
    tempMoney=3000;//在这里改变了,银行可是亏大了,银行可要追究你刑事责任了,^_^
    return oldMoney3+tempMoney;
}

int ZhuanZhang4(const int &tempMoney)
{、、
//    tempMoney=4000;    //这下银行就放心了。添加上就错了,是被const修饰的
    return oldMoney4+tempMoney;
}

强调一点:把内存中的数据从一个地方拷贝到另外一个地方,是费时间的,如果传给地址,让计算机去找,这个比较快。内存中地址的寻找定位可是光速呀。不要发愁这个了。

完整程序:
//为什么声明4个变量呢,代表着3种转帐方式,方便理解,oldMoney代表你从前的钱数,最后两个都是引用,一个做了限定,另外一个没有限定。

int oldMoney1=2000;//你从前的2000万钱
int oldMoney2=2000;
int oldMoney3=2000;
int oldMoney4=2000;

//4个转帐函数,对应3种不同的转帐过程。后两种是引用

int ZhuanZhang1(int tempMoney)//第一种,传值
{
    return oldMoney1+tempMoney;
}

int ZhuanZhang2(int *tempMoney)//第二种方式:开辟一个指针变量
{
    return oldMoney2+*tempMoney;
}

int ZhuanZhang3(int &tempMoney)//第三种方式:把自己的地址传过去,不在经过指针变量的中转。
{
    tempMoney=3000;//呵呵不安全了,银行可是亏大了
    return oldMoney3+tempMoney;
}

int ZhuanZhang4(const int &tempMoney)//第四种方式,用const限定
{
//    tempMoney=4000;    //银行满意了,添加上就错了,是被const修饰的,呵呵,它可穿上防弹衣了。
    return oldMoney4+tempMoney;
}

void main()
{
    int newMoney1=1000;//你要中转的1000万钱
    int newMoney2=1000;
    int newMoney3=1000;
    int newMoney4=1000;

    // nowMoney代表转帐后你的钱的数目
    int nowMoney1=ZhuanZhang1(newMoney1);
    int nowMoney2=ZhuanZhang2(&newMoney2);
    int nowMoney3=ZhuanZhang3(newMoney3);
    int nowMoney4=ZhuanZhang4(newMoney4);

    //要转帐的钱
    printf("%d\n",newMoney1);
    printf("%d\n",newMoney2);
    printf("%d\n",newMoney3);
    printf("%d\n",newMoney4);
    printf("\n");

    //现在的钱
    printf("%d\n",nowMoney1);
    printf("%d\n",nowMoney2);
    printf("%d\n",nowMoney3);
    printf("%d\n",nowMoney4);
}

结果:
1000
1000
3000
1000

3000
3000
5000
3000

    好了,大功告成了,指针与引用是C++语言的上乘内功。一定要练好这样的内功,否则后面的秘籍就只能看看了。可要多吃几口呀![em1][em1][em1][em1][em1]^_^^_^。

    要知下回如何,且听下次分解。

回复列表 (共11个回复)

沙发

顶一个。。。

板凳

楼主真可爱,谢谢咯!

3 楼

楼主真辛苦~~

4 楼

真是好贴啊,谢谢楼主

5 楼

受教了

6 楼

我对指针和引用就是掌握的不好,该怎么办呀?

7 楼

谢谢楼主,经典啊,还要多看几遍和指针还是有区别啊

8 楼

楼主辛苦了!说得好!

9 楼

看见好贴应该顶,用处很大,谢谢

10 楼

好幽默的解释阿,比我们老师上课讲得生动多了,先存起来。。

我来回复

您尚未登录,请登录后再回复。点此登录或注册