& 取地址符的用法总结

来源:互联网 发布:数据交换 编辑:程序博客网 时间:2024/05/09 16:37

转自百度文档



一种是按位与 

1 & 2 = 0

一种是取地址

int* p = &a;

 一种是声明引用,相当于定义变量别名:  

 int a = 3;  

int& b = a; // ba的引用,ab是同一个变量

b = 4; // a也变化为4

int c = 2;  

b = c; // 是赋值给ba,而不是把b作为c的引用,引用一旦被声明,引用对象不可更改   

引用的实质是指针的简化运用版,上面的代码等价为:

 int a = 3;  

int* const b = &a; // 常指针,b的位置不能更改,相当于引用不能更改自身的引用对象*b = 4;   

 

 

所以引用省去了声明时的取地址操作和对变量内存地址引用时的解引用操作,而且引用不能随意被更改,站在指针的角度上说,引用的意义等价于一个常指针,也就是不能改变自己指向位置的指针。   

 

 

引用在作为参数传递的时候,传递的是实参本身,c++里面类设计经常要传递整个类作为参数,但如果在不必要的时候使用传统的按值传递,效率损失可见一斑:

 class foo

{ public:

.... int a;

double b;

string c; };  

void bar(foo f) { //输出abc }   比如这个函数bar传参的时候是按值传递,也就是实参的所有数据被重新复制到参数f里,构造了一个新对象f,它只是输出参数fabc成员,所以必要重新构造一个临时对象f,这样造成了效率的损失,解决方法有2

void bar1(foo* f)

{ cout<< f->a << f->b << f->c; }

var bar2(foo& f)

{ cout<<f.a<<f.b<<f.c; }  

 这2种方式的运作机制是相同的,但是后者要更简洁和优美一些,特别是在操作多层间接指针的函数里面,直接使用指针的话,过多取地址&和解引用*容易造成代码混乱,降低可读性。  

  

  再如friend Complex operator +(Complex&,Complex&);

 

在这个重载语句中 "Complex&""&"作用是什么假如不写"&"有什么影响? 

还有在类中定义时是不带参数如friend Complex operator +(Complex&,Complex&); 

在实现中再定义friend Complex operator +(Complex& temp1,Complex& temp2); 

    

 

 

这个重载语句中 "Complex&""&"作用是,表示调用函数时传递参数是以引用方式传递的,这样子在函数中操作的对象就是调用外面的那个对象本身。  

 

假如不写"&"的话,其影响有两个。

一个是,当你想对这个参数的对象进行修改的话,在函数返回后,这个修改的值不会改变。第二,在做参数传递的时候,不加"&"的话,传递的过程中,会创造一个临时对象,这样会造成一定的效率浪费。  

 

在编程中,函数分声明和定义。声明只是告诉编译器,存在这个函数,这个时候可以不带参数名称。而定义的时候,就必须实行函数本体,这个时候就必须带上参数的名称了。

 

 

     

引用“& " 的用法与指针的用法

//class  c

alss Test{  // }  

 

//创建一个Test 的对象 

Test Ta; 

 

&b = Ta; //理解成PHP的引用就可以了...这相当于把b的地址指向Ta,,也就相当于bTa相等,都指定同一个内存地址

 

接下来是转别人的例子:  

 

引用是C++引入的新语言特性,是C++常用的一个重要内容之一,正确、灵活地使用引用,可以使程序简洁、高效。

首先我们来讲一下指针  

比如 int a,b 

int *pointer_1, *pointer_2 

.... 

pointer_1 = &a; pointer_2 = &b 

swap(pointer_1, pointer_2); 

........... 

 

在子函数中是 

 

swap(int *p1, int *p2) 

这里实行交换操作

 。。。。  

解释指针本质在主函数中 

把指针变量pointer_1pointer_2传递 

使p1p2也指向a,b,先进行交换,交换后,pointer_1p1指向了

但是pointer_2p2指向了a,然后p1p2释放了,但是交换却成功了!    

 

下面讲引用转() 

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。 

 

引用的声明方法:类型标识符&引用名=目标变量名  

 

【例1】:

int a;

 int&ra=a; //定义引用ra,它是变量a的引用,即别名 

 

说明:  

 

1&在此不是求地址运算,而是起标识作用。  

 

2)类型标识符是指目标变量的类型。  

 

3)声明引用时,必须同时对其进行初始化。  

4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。  

 

ra=1; 等价于 a=1;   

 

5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra&a相等。

6不能建立数组的引用。因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。   

 

引用应用  

 1、引用作为参数  

 引用的一个重要作用就是作为函数的参数。以前的C语言中函数参数传递是值传递,如果有大块数据作为参数传递的时候,采用的方案往往是指针,因为这样可以避免将整块数据全部压栈,可以提高程序的效率。但是现在(C++中)又增加了一种同样有效率的选择(在某些特殊情况下又是必须的选择),就是引用。   

【例2】:  

void swap(int&p1, int&p2) //此处函数的形参p1, p2都是引用   

{

int p;

p=p1;

p1=p2;

p2=p; }     

为在程序中调用该函数,则相应的主调函数的调用点处,直接以变量作为实参进行调用即可,而不需要实参变量有任何的特殊要求。如:对应上面定义的swap函数,相应的主调函数可写为:  

 main( )  

{     

inta,b;   

 cin>>a>>b; //输入a,b两变量的值    

swap(a,b); //直接以变量ab作为实参调用swap函数   

 cout<<a<< '' '' <<b; //输出结果  }     

上述程序运行时,如果输入数据10 20并回车后,则输出结果为20 10。  

 

 由【例2】可看出:   

1传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。   

2使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。   

3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。   

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。       

自己理解的:::引用就好象取了另一个名字,比如我现在叫小明,取个外号叫猪头,但是所指的是同一个人而已  

 我是如此理解的,我们应该知道皮影戏,人用线操做木偶,我们可以这个样子想,比如我们可以用手操作木偶去办事,木偶做的事不就是自己直接在做的啊,所以在子函数中操作就等于在主函数中操作一样(我自己理解的可能有错误)     

但是我们可能碰到例如

intStackEmpty(SqStack s)

{  if(s.top == s.base)

return TRUE;  

 return FALSE; }     

int  Push(SqStack&s, SElemType e)

{  if(s.top - s.top>= s.stacksize)

{s.base=(SElemType*)realloc(s.base,(s.stacksize + STACKINCREMENT) * sizeof(SElemType)); 

if(!s.base) 

exit(OVERFLOW);  

s.top = s.base + s.stacksize; 

s.stacksize += STACKINCREMENT;  

   } 

*s.top++ = e; 

return TRUE; 

}   

int Pop(SqStack&s, SElemType&e) 

if(s.top == s.base) 

return FALSE;  

    

e=*--s.top;

return TRUE; } 

 

在堆栈操作中,有的不用&,有的要用&,为什么呢?  什么时候使用引用  

1、现在可以总结一下什么时候使用引用这个问题了。

首先我们要看看什么时候必须使用引用  

流操作符<<>>、赋值操作符=的返回值  

拷贝构造函数的参数、赋值操作符=的参数  

2、其它下面的情况都是推荐使用引用,但是也可以不使用引用。如果不想使用引用,完全可以使用指针或者其它类似的东西替代:    

异常catch的参数表    

大对象作为参数传递    

返回容器类中的单个元素 

返回类数据成员(非内建数据类型成员)   

返回其它持久存在的,且获得者不负责销毁的对象

 

另外一些情况下,不能返回引用:  

+-*/四则运算符

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 部队体能差的人怎么办 上环5天同房了怎么办 肾结石有3mm了怎么办 4*3mm肾结石好痛怎么办 做完肾结石积水后迟续发烧怎么办 血糖高有肾结石反复发高烧怎么办 肾里面有小结石怎么办 大于2厘米的结石怎么办 双肾结石肾盏扩张怎么办 边防消防警卫部队改革义务兵怎么办 汽车年检尾气复检不合格怎么办 车辆年检尾气不合格复检怎么办? 在瓜子上买车复检有问题怎么办 更换车壳车架号怎么办 吸完甲醛的绿萝怎么办 如果公务员复检不合格有异议怎么办 国考公务员政审没有毕业证怎么办 打针硬块4年不消怎么办 外墙补起来难看不好卖怎么办 杠精现实中应该怎么办 发现记者报道假新闻怎么办 2018消防兵转制到期士官怎么办 小孩睡觉老想着军训怎么办 1岁宝宝太老实了怎么办 上课小孩很调皮不听话怎么办 初中学生上课爱说话调皮怎么办 8个月婴儿疝气怎么办 头部疤痕不长发怎么办呢 有纹身想去当兵怎么办 在部队干活的钱怎么办 新兵5公里超过标准时间怎么办 17个月婴儿裹手怎么办 7个月婴儿裹手怎么办 俩月孩子裹手怎么办 婴儿 3个月 裹手怎么办 一岁宝宝裹手怎么办 5个月宝宝裹手怎么办 不想让孩子裹手怎么办 四个月宝宝裹手怎么办 开车撞狗了跑了怎么办 母螃蟹抱卵了怎么办