引用与取地址

16 篇文章 0 订阅
10 篇文章 0 订阅

转载自:http://blog.sina.com.cn/s/blog_4cd5d2bb0100bizc.html

     http://blog.csdn.net/zenny_chen/article/details/2512056 

引用实际上就是给同一个变量取了多个名字。  
举个例子:  
有个人的名字叫a,之后又改名叫b,这时a和b都是指这个人,这样b就引用了a,即b就是a。

int   &a   =   b;    ........1  
int   *a   =   &b;   ........2  
在1的情况下,   只分配了b的空间  
在2的情况下,   分配了a和b的空间  
 

引用是C++的叫法  
取地址是C的叫法
 

也就是说作为形参时,如果出现&,就是C++里的引用,而作为实参时出现&就是C里的取地址 ,之所以在写C程序时再出现&不会报错,是因为现在的编译环境基本及支持C又支持C++

   
简单说:  
引用,需要一个对象  
取地址,不用。  


   
另:把引用说是指针,也不为过。其区别可以这么说  
引用不能改变,指针可以改变。  
引用有安全机制检查,指针没有。
  

   
引用的2大作用:    
      1)作为函数的参数,用于提高效率(如常量入参,返回类的成员变量的值)、返回数据作为函数的参数,用于提高效率这里主要是指用类实例作为参数,因为如果不是用引用,也不使用指针,那么在参数的传递过程中,将有一个隐含的调用类的构造函数的操作,也就是说将构造一个新的类作为参数,使用引用将避免这个过程,如果担心类中的成员被修改,那么可以再加上const修饰符。引用传递可以在函数里直接改变实参,而值传递只是改变副本。 

      2)简化代码,使代码易读。如:  
          要使用a->b->c->d->e->f->g,g是一个多重嵌套类中的一个整数成员,书写很麻烦,也容易错。  
 这时:  
          int   &z   =a->b->c->d->e->f->g;  
          以后直接使用z,因为他们的存贮单元本来一致,所以也根本没有效率的损失。

我们首先看下面一个简单的例子:

#include <stdio.h>
int main(void)
{
    int a = 0;
    int *p = &a;
    printf("The value is: %d/n", *p);
    return 0;
}


上面代码中,指针p指向变量a的地址。在C/C++中,每个变量都有其相应的地址,通过在变量标识符前加&符号即可获得变量的地址。

那么我们这么写可以吗?int *p = &0x01000;

这显然不行。因为对于一个数值常量,它是没有地址的。而变量之所以有地址就是因为要有一个存储单元对变量进行标识(当然,变量也可以直接映射到某个寄存器)。

我们再看下面的代码:


#include "stdio.h"
int main(void) 
{ 
    int a = 0; // &a = 0x0012ff60 
    int *p = &*(int*)0x0012ff60; 
    printf("The value is: %d/n", *p); 
    return 0; 
}


上面代码又是怎么回事呢?

先前已经调查过变量a的地址——0x0012ff60,那么这里的指针p实际上也是指向变量a的地址。

首先,将0x0012ff60作为int*,这时它与&a是等价的。

然后*(int*)0x0012ff60表示取变量a的内容。

最后,&*(int*)0x0012ff60表示再脱去*(int*)0x0012ff60的解引用,相当于又变为(int*)&a。

因此,这里的&与第一个例子中的&是不同的语义。这里的&不是取地址,因为一个*(int*)0x0012ff60不是变量,它是没有地址的。每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等。地址标识在连接后即可确定逻辑地址值。简而言之,&作为取地址操作,当且仅当&后面跟着的是变量或函数标识符。所以这里的&表示脱去解引用。

由此我们可以得出:&作为取地址操作时,其行为结果是在编译时就被确定的;而*,解引用操作(或取内容)操作,其行为结果只能在运行时才可被确定。

再看下面的例子,加深印象:


#include "stdio.h"
int main(void)
{
    int a = 0;
    int *p = &*&*&a;
    printf("The value is: %d/n", *p);
    return 0;
}

不过,&符号不象解引用*能用多次,它只能放在变量标识符或一次解引用前。下面举一个例子


int main(void)
{
    int a = 100;
    int *p = &a;
    int **pp = &p;
    int **qq = &*&*pp;    // OK
    int **rr = *&*&pp;    // OK
    int **ss = &&**pp;    // ERROR
}

由于经过一次&来脱去解引用之后,当前表达式就不为左值。而&必须放在一个左值前,因为只有左值才能确保引用是有效的,呵呵。
在C++中,&还可以表示引用,这个就不多说了。


#include "iostream"
using namespace std;
int main(void)
{
    int a = 0;
    int &r = a;
    cout << "The value is: " << r << endl;
    return 0;
}





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值