http://blog.sina.com.cn/recoo[订阅]
字体大小: 正文
变量的引用,指针变量的引用,引用作为返回值,堆中变量的引用。(2008-04-06 22:08:31)
1.变量的引用
对一个数据可以使用引用(reference),引用的作用是为变量起一个别名。
int a;//定义整型变量a
int &b=a;//声明b是a的引用
上面语句声明b是a的引用,即b是a的别名。&是引用声明符(不是取地址运算符)。将b声明为a的引用,不需要为b另外开辟内存单元。b和a占内存中的同一个存储单元,它们具有同一地址。
在声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。在声明变量b是变量a的引用后,在它们所在函数执行期间,该引用类型变量b始终与其代表的变量a相联系,不能再作为其他变量的引用。
int a1,a2;
int &b=a1;//ok
&b=a2;error: ISO C++ forbids cast to non-reference type used as lvalue
引用不是一种独立的数据结构,必须指定其代表某一类型的实体(如变量、对象),不能定义引用数组和指向引用的指针。
2.引用的使用
int  main(){    
  int i_one=6;
  int &r_int=i_one;
 
  cout<<"i_one="<<i_one<<",&i_one="<<&i_one<<endl;
  cout<<"r_int="<<r_int<<",&r_int="<<&r_int<<endl;
  cout<<endl;
 
  int i_two=9;
  r_int=i_two;
  cout<<"i_one="<<i_one<<",&i_one="<<&i_one<<endl;
  cout<<"i_two="<<i_two<<",&i_two="<<&i_two<<endl;
  cout<<"r_int="<<r_int<<",&r_int="<<&r_int<<endl;
  system("PAUSE");
  return EXIT_SUCCESS;
}
结果:
i_one=6,&i_one=0x22ff74
r_int=6,&r_int=0x22ff74
 
i_one=9,&i_one=0x22ff74
i_two=9,&i_two=0x22ff6c
r_int=9,&r_int=0x22ff74
可以发现[1]引用r_int与它的本体变量i_one占用的是用一个地址;[2]当借助引用改变变量的值时,其本体变量的值也随之改变。
3.指针变量的引用
可以有指针变量的引用,
int  main(){
  int arr[]={1,2,3};       
  int *p=arr;
  int *&r=p;
  cout<<"r="<<r<<",p="<<p<<endl;
  cout<<"r->"<<*r<<",p->"<<*p<<endl;
  cout<<endl;
  int a_int=9;
  p=&a_int;//ok.
  cout<<"r="<<r<<",p="<<p<<endl;
  cout<<"r->"<<*r<<",p->"<<*p<<endl;
  system("PAUSE");
  return EXIT_SUCCESS;
}
结果:
r=0x22ff60,p=0x22ff60
r->1,p->1
 
r=0x22ff54,p=0x22ff54
r->9,p->9
这里通过引用改变了指针变量的指向。同样可以将引用指向void指针。
int  main(){
  int arr[]={1,2,3};
  void *p=arr;
  void *&r=p;
  cout<<"p->"<<*(int *)p<<",r->"<<*(int *)r<<endl;
  system("PAUSE");
  return EXIT_SUCCESS;
}
结果:
p->1,r->1
但是,不能对void进行引用;不能建立数组的引用;引用本身不是类型,所以没有引用的引用;也没有引用的指针。
用引用方式传递函数参数,其“效果”与使用指针的“效果”是一样的。
4.使用引用返回值
const float pi=3.14;
float f;
 
int  main(){
  float f1(float=5);
  float& f2(float=5);
  float a=f1(); //①
  float& b=f1();//②error:invalid initialization of non-const reference of type 'float&' from a temporary of type 'float'
  float c=f2();//③
  float& d=f2();//④
  system("PAUSE");
  return EXIT_SUCCESS;
}
 
float f1(float r){
  f=r*r*pi;
  return f;
    
 
float& f2(float r){
  f=r*r*pi;
  return f;
}
[1]函数f1()返回一个一般的float变量;函数f2()返回一个float变量的引用;main()中1,2,3,4“效果”相同,得到的值是78.5。
 
[2]①中会将全局变量f的值78.5赋给一个临时变量temp(由编译器隐式的建立),再由临时变量赋给变量a。
 
[3]②错误的原因是不能对一个临时变量temp进行引用。
 
[4]③在返回值时并没有隐式的建立临时变量temp,而是直接将全局变量f返回给主函数。
 
[5]④在主函数中都不使用定义变量,而是直接使用全局变量的引用,这种方式是全部4种中最节省内存空间的。但必须注意它所引用的变量的有效期,此处全局变量f的有效期肯定长于引用d,所以是安全的。
如果将一个局部变量的引用返回,则会出现警告,
const float pi=3.14;
 
int  main(){
  float& f2(float=5);
  float c=f2();
  system("PAUSE");
  return EXIT_SUCCESS;
}
 
float& f2(float r){
  float f=r*r*pi;[Warning] reference to local variable `f' returned
  return f;
}
5.函数调用作为左值(返回一个引用时)
通过上面的示例发现,只要避免将局部栈中变量的地址返回(即返回一个临时的引用),则可以返回一个引用使得函数调用表达式成为左值。
下面是一个判断奇偶的函数,
int arr[]={1,2,3,4,5,6,7,8,9};
int& check(int*,int&,int&);
 
int  main(){
  int t_odd=0,t_even=0;
  int size=9;
  for(int *p=arr;p<(arr+size);p++){   
    check(p,t_odd,t_even)++;//将函数调用作为左值
 
  cout<<"odd="<<t_odd<<",even="<<t_even<<endl;    
  system("PAUSE");
  return EXIT_SUCCESS;
}
 
int& check(int*p,int &odd,int &even){
  if((*p/2*2)==*p)
    return even;
  else
    return odd;
check()函数返回的是一个引用,如果是奇数则奇数引用值加1,否则偶数引用值加1。这里直接返回的是形参引用,所以有效的避免了返回临时引用的问题。函数的自加操作其实就是整型变量t_odd和t_even的自加操作。
6.操作堆中变量的引用
const double PI=3.14;
int circle_area();
 
int  main(){
  if(circle_area())
    cout<<"failed."<<endl;
  else
    cout<<"successed."<<endl;      
  system("PAUSE");
  return EXIT_SUCCESS;
}
 
int circle_area(){
  double *p=new double;
  if(!p){
    cout<<"error memory allocation."<<endl;
    return 1;
  }
  double &r=*p;
  cout<<"the radius:";
  cin>>r;
  cout<<"area="<<r*r*PI<<endl;
  delete &r;
  return 0;
}
函数circle_area()中指针p接受new返回的堆空间地址,必须进行检验,看是否内存分配成功;声明指针变量p的引用r。返回堆空间有两种方式,方式一delete p;方式二delete &r。
加载中,请稍候...
  • 评论加载中,请稍候...

验证码:请点击后输入验证码  收听验证码

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

相关博文
读取中...
推荐博文
读取中...