C++杂记:引用类型

引用类型是C++11标准中新增的一种复合类型,作用是为对象起了另外一个名字。

//引用i变量,起名为j
int i = 0;
int &j = i;
//这样也可以
int i = 0, &j = i;

*需要注意的是

1.引用类型在定义时必须进行初始化

int &j;//错误

2.引用的类型和初始化的类型必须严格匹配

double i = 0.0;
int &j = i;//错误

3.引用类型初始值必须是一个对象,而不能是一个常值

int &j = 0;//错误

4.引用类型本身不是一个对象,不能定义引用的引用,这一点和指针不同。

int *p1 = nullptr,**p = &p1;//二级指针正确
int i=0,&j=i;
int &&k = i; //错误

5.引用类型定义及初始化后无法再改变,对它赋值、取值都是对所引用的变量赋值、取值(包括sizeof等)

sizeof(int&);//4
sizeof(char&);//1
sizeof(double&);//8

6.引用类型所占空间大小和指针相同(与字长对应,x86 是 4,x64 是 8)

7.可以使用指针类型的引用,但不允许使用指向引用的指针

int i = 0;
int *p = &i, **ps = &p;
int &*j = nullptr;//对引用类型的指针,错误
int *&q = p;//指针类型的引用,正确
int **&qs = ps;//二级指针的引用,正确

8.*对const对象的引用,不能给引用进行赋值操作

const int i = 1;
const int &j = i;//正确
j = 2;//错误,常量引用不能赋值
int &k = i;//错误,非常量引用不能初始化为常量

常量引用特殊的地方在于它的初始化可以是任何表达式,只要该表达式的结果可以转换成对应常量类型即可。

int i1 = 1; const int &j1 = i1;//正确
double i2 = 1.5; const int &j2 = i2;//正确,初始化为1
const double i3 = 1.5; const int &j3 = i3;//正确,初始化为1
const int &j4 = 1;//正确
const int &j5 = 1.5;//正确,初始化为1

由于常量引用可以引用非常量对象,所以可以通过改变所引用的非常量对象改变常量引用,但不可通过常量引用来改变。

int i1 = 1; const int &j1 = i1;
j1 = 10;//错误,常量引用不可赋值
int i1 = 1; const int &j1 = i1;
std::cout << i1 << "," << j1 << std::endl;//1,1
1 = 10;
std::cout << i1 << "," << j1 << std::endl;//10,10
int &j2 = i1;
j2 = 100;
std::cout << i1 << "," << j1 << "," << j2 << std::endl;//100,100,100

然而对于其他类型的对象来说,就不会因原变量而改变,如double类型。

double i1 = 1.8; const int &j1 = i1;
std::cout << i1 << "," << j1 << std::endl;//1.8,1
i1 = 10.8;
std::cout << i1 << "," << j1 << std::endl;//10.8,1
double &j2 = i1;
j2 = 100.8;
std::cout << i1 << "," << j1 << "," << j2 << std::endl;//100.8,1,100.8

这是因为int常量引用在定义初始化时得到的引用的是编译器创建的一个临时量,而并非是double类型的i1。

double i1 = 1.8;
const int x = i1;//编译器编译时创建的临时量,x=1
const int &j1 = x;

 

--->一个常见的用法是用在函数传递参数。

#include<iostream>
void swap1(int *a, int *b)
{
	*a += *b;
	*b = *a - *b;
	*a -= *b;
	return;
}
void swap2(int &a, int &b)
{
	a += b;
	b = a - b;
	a -= b;
	return;
}
int main(int argc, char* argv[])
{
	int x(0), y(1);
	swap1(&x, &y);
	std::cout << x << "," << y << std::endl;//1,0
	swap2(x, y);
	std::cout << x << "," << y << std::endl;//0,1
	return 0;
}

        用指针和引用都可以完成对实参的改变,引用要方便许多。函数的形参是实参的引用,直接使用就可以,不用再麻烦的取地址。这样以来,想在函数里操作实参的就加引用就可以,指针同样可以用 *&p 作为形参来操作实参。

        还需要注意的是,不可创建数组名的引用,因为数组名并不是一个对象。所以需要将数组作为函数参数时,建立一个指向数组的指针即可。

#include<iostream>
void func(int *&a)
{
	a[0] = 10, a[1] = 20;
	return;
}
int main(int argc, char* argv[])
{
	int a[2] = { 1,2 };
	std::cout << a[0] << "," << a[1] << std::endl;//1,2
	int *p = a;
	func(p);
	std::cout << a[0] << "," << a[1] << std::endl;//10,20
	return 0;
}

END

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值