C++学习总结9--C++的引用(Reference)

小记:静默如初,安之若素

C++的引用(Reference)

1. 定义
1)引用就是某个变量的别名,对引用的操作与变量操作完全相同。
2)语法
类型 & 引用名 = 变量名;
注:引用定义时必须初始化,初始化后绑定的变量不能再做修改;
注:引用的类型与初始化时绑定的变量类型一致;

eg:
	int a = 123;
	int &b = a;//b就是a的引用(别名),对引用初始化
	b++;
	cout<< a << endl;//123
	
	int c = 321;
	b = c;//将c的值赋值给b,等价赋值给a
	cout << a << endl;//321
	
  1 #include <iostream>
  2 using namespace std;
  3 
  4 int main(int argc, char * argv[])
  5 {
  6   int a = 10;
  7   int &b = a;//b引用了a,b就是a的别名,b的内存空间与a相同
  8   cout<< "&a = "<< &a <<" , a = "<< a <<endl;
  9   cout<< "&b = "<< &b <<" , b = "<< b <<endl;
 10 
 11   //对引用进行操作和对变量进行操作相同
 12   b++;
 13   cout<<"a = "<< a <<endl;//11
 14   cout<<"b = "<< b <<endl;//11
 15   a++;
 16   cout<<"a = "<< a <<endl;//12
 17   cout<<"b = "<< b <<endl;//12
 18   
 19   //引用定义时必须初始化
 20   //int &r;//error: ‘r’ declared as reference but not initialized
 21   
 22   //初始化后绑定的变量不能再做修改
 23   int c = 66;
 24   b = c;//将c的值赋值给b(a), 而不是修改引用目标
 25   cout<<"a = "<< a <<endl;//12
 26   cout<<"b = "<< b <<endl;//12
 27   
 28   //引用的类型与变量的类型一致
 29   //double &d = c;//error: invalid initialization of non-const reference of 
 30                   //type ‘double&’ from an rvalue of type ‘double’
 31 
 32   return 0;
 33 } 

2. 常引用
1)定义引用时加const修饰,即为常引用,不能通过常用引用修改引用的目标。
const 类型 & 引用名 = 变量名;<=等价=> 类型 const & 引用名 = 变量名;

eg:
  int a = 100;
  const int *pa = &a; <=等价=> int const *pa = &a;
  const int &b = a;//b就是a的常引用
  b++;//error
  a = 100;
  cout<< b << endl;//100
  1. 普通的引用只能引用左值,而常引用也叫万能引用,既能引用左值也能引用右值。
eg: 
  int a = 0; 
  a = 100;//a是左值
  100 = 200;//100是右值
eg:普通的引用只能引用左值
  int a = 100;
  int &b = a;//ok
  int &b = 100;//error,
  b = 200;//error,该语句表示100 = 200,
  const int &b = a;//ok
  const int &b = 100;//OK

3)关于左值和右值
左值:可以放到赋值运算符(=)的左侧变量(也可以放到右侧),一般普通的变量都是左值;

普通的变量;
赋值表达式;
前++,前--表示式结果

右值:只能放到赋值运算符(=)的右侧变量,一般常量都是右值;

常量;
大多数表示式结果;
函数返回临时变量(将亡右值)

3. 引用型函数参数
  1)将引用用于函数的参数,这时形参就是实参的别名,可以通过形参直接修改实参的值,同时避免参数传递的过程,减小函数调用的开销。
  2)引用型参数有可能意外修改实参的值,如果不希望修改实参本身,可以将形参定义为常引用,提高传参效率的同时还可以接受常量型的实参。

(1)通过形参直接修改实参的值

  1 #include <iostream>
  2 using namespace std;
  3 
  4 //两个整形数用异或交换效率更高(C 语言)
  5 void swap1(int *x, int *y)
  6 {
  7   *x = *x ^ *y;//011 ^ 101 = 110(x)
  8   *y = *x ^ *y;//110 ^ 101 = 011(y)
  9   *x = *x ^ *y;//110 ^ 011 = 101(x)
 10 }
 11 
 12 //两个整形数用异或交换效率更高(C++ 语言)
 13 void swap2(int &x, int &y)
 14 { 
 15   x = x ^ y;//011 ^ 101 = 110(x)
 16   y = x ^ y;//110 ^ 101 = 011(y)
 17   x = x ^ y;//110 ^ 011 = 101(x)
 18 } 
 19 
 20 
 21 int main(int argc, char *argv[])
 22 { 
 23   int a = 3, b = 5;
 24   cout<<"a = "<< a <<" b = "<< b <<std::endl;
 25   //swap1(&a, &b);
 26   swap2(a, b);
 27   cout<<"a = "<< a <<" b = "<< b <<std::endl;
 28   return 0;
 29 }

(2)提高传参的效率

  1 #include <iostream>
  2 using namespace std;
  3 
  4 struct Student{
  5   char name[128];
  6   int age;
  7 };
  8 
  9 void print(const Student& s)
 10 {
 11   cout<< s.name << "," << s.age/*++*/ << endl;
 12 }
 13 
 14 int main(int argc, char *argv[])
 15 { 
 16   const Student stu = {"zhang", 28};
 17   print(stu);
 19   return 0; 
 20 }

4. 引用型函数返回值
1)可以将函数的返回值声明为引用,避免返回值所带来的内存开销;
2)如果一个函数返回类型被声明为普通引用,那么该函数返回值是一个左值;
3)如果不希望函数直接返回左值,可以返回常引用;
注:不要从函数中返回局部变量的引用,因为所引用的变量内存会在函数返回以后被释放,但是可以返回成员变量,静态变量以及全局变量的引用

eg:
	int func(void{
		static int a = 100return a;//int tmp = a;实际返回结果是tmp
	}
	-----------------------
	int &func(void)
	{
		static int a = 100;
		return a; //没有tmp, 实际返回的就是a的自身
	}
	func() = 200;//ok:
	--------------------------------------
	const int &func(void)
	{
		static int a = 100;
		return a; //没有tmp, 实际返回的就是a的自身
	}
	func() = 200;//error

//笔试题:指针和引用的区别
5. 引用和指针
1)如果从C角度去看引用,其本质就是指针,但是在C++中建议使用引用而不是指针;

eg:
	int a = 100;
	int &ra = a;
	int *const pa = &a;
	*pa <==> ra

2)指针可以不做初始化,其目标可以随意改变(指针常量除外);而引用必须初始化,而且引用的目标不能再改变。

eg:
   int a = 100, b = 200;
   //指针
   int *p;//ok,指针可以不做初始化
   p = &a;//p指向a
   p = &b;//p指向a
  ----------------------
  //引用
  int &r;//error
  int &r = a;//引用必须定义初始化
  r = b;//ok,但是该过程是赋值操作,不能改变引用的目标

//了解
3)定义指针的时候可以定义指针的指针(二级指针),但是不能定义引用的指针。

eg:
	int a = 100int *p = &a;
	int **pp = &p;//二级指针
	-----------------------------
	int &r = a;
	int &*pr = &r;//error

4)可以定义指针的引用(指针别名),但是不能定义引用的引用。

eg:
	int a = 100int *p = &a;
	int *& rp = p;//ok,指针的引用,给指针变量起的别名
	-----------------------------
	int &r = a;
	int &&rr = r;//error
	int &rr = r;//ok.不能叫引用的引用,就是一个普通的引用,等于给a起了另一个别名。
5)可以定义指针数组,但是不能定义引用数组。

```cpp
eg:
 int a = 10, b = 20, c = 30;
 int *parr[3] = {&a, &b, &c};//ok. 指针数组
 int &parr[3] = {a, b, c};//error

6)可以定义数组引用(给数组起别名)

eg:
	int arr[3] = {10, 20, 30};
	int (&rarr)[3] = arr;//ok, arr 的别名

7)和函数指针类似,也可以定义函数的引用(给函数起别名),其语法规则和函数类似

eg:
 void func(int a, int b){...}
 int main(void)
 {
 	void (*pfunc)(int, int) = func;//函数指针
 	pfunc(10, 20);
 	----------------------------
 	void (&rfunc)(int, int) = func;//函数引用
 	rfunc(10, 20);
 }

注:需要与C中的typedef进行区分,typedef是指对类型进行起别名,引用就是某个变量的别名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值