C++引用及C11的一些关键字

引用

引用概念

	引用不是定义一个新的变量,而是给已知的变量取一个别名,定义一个引用变量之后,编译器并不会在内部为它开辟内存,而是和其引用变量共用一块内存空间。
	类型& 引用变量 = 引用实体;

引用特性

引用变量在定义时必须初始化
同一个引用变量不能引用多个实体
同一个变量可以被多次引用

int a = 10;
int b = 20;
//int &ra;  在编译时会出错。
int &ra = a;
int &rb = a;
//int &rb = b; 编译时报错。
printf("%p, %p, %p\n", &a, &ra, &rb);

在这里插入图片描述

由此可见,引用变量与引用实体指向通一块内存。

const常引用

我们知道被const修饰的变量不能被随意修改,那该如何引用被const修饰的变量?这就需要常引用。

const int a = 10;
//int& ra = a;
const int& raa = a;

通过编译可以知道,直接用一般引用是不能引用const所修饰的变量的,必须显式声明引用也是const类型的。

double d = 12.34;
//int& rd = d;
const int&rdd = d;

double类型的不能被int所引用,但是却可以被const int所引用,这是为什么呢。
所谓引用就是将rdd和d指向同一块内存空间,但是因为两者类型不同,这中间肯定有类型强转,所以rdd只指向double整数的那块空间,但是此时这块空间不是完整的d,我们也不知道名字,所以编译器就将这块内存当做常量来处理,这样用const修饰就可以被引用。

引用与指针

我们可以通过引用与指针来分别修改一个变量的值

int a = 10;
int& ra = a;
int *pa = NULL;

ra = 20;
*pa = 20;


从汇编代码上看,指针和引用在本质上并没有区别,也可以说引用底层实现原理就是使用指针。既然两者底层实现基本都相同,所以在效率上两者也是不相上下的。
回到我们之前说的,一个引用只能引用一个变量,但是一个指针却可以指向任意地址,既然两者底层实现都相同,那么引用应该也可以引用多个变量才是。
我们可以把引用int& ra = a;理解为 int * const ra = &a,用一个const来修饰引用变量,这样引用变量的值就不能被随便修改。

引用在定义时必须初始化,指针可以不同
引用在引用一个实体后不能再引用其他实体,但是指针可以指向任意一个地址
在sizeof中,引用大小为引用引用类型的大小,指针始终是地址空间所占的字节数
引用自加是给变量本身加一,但是指针是所指向类型的大小加一
有多级指针,但是没有多级引用
在访问实体时,指针需要显式解引用,但是引用编译器自己实现
没有NULL引用,但是有NULL指针
使用引用比使用指针更安全

内联函数

	有些代码块很小的函数,在调用时也需要开辟栈帧,这无疑会降低程序运行的效率,所以C++允许以inline关键字声明的函数作为内联函数,编译器会在调用内联函数的地方展开,没有函数压栈的开销,以此来提升程序运行的效率。
	内联函数是一种典型的以空间换取时间的做法,所以代码很长或者递归的函数不适合作为内联函数
	inline关键字对于编译器来说只是一个建议,如果函数体内有循环递归,编译器会自动忽略内联。

宏与宏函数

宏与宏函数增强了代码的复用性,并且也提高了性能,但是对于宏来说,在预处理阶段已经被编译器替换,无法检查宏函数的类型以及返回值,不方便调试,对于++,–等操作因为多次调用导致结果出错,这无疑大大降低了宏的实用性。
但是在C++中,可以用内联函数来替换宏,同样可以达到目的。

C++11的一些关键字

auto

C++11中,赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

int a = 10;
auto b = a;
auto c = 'x';
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;

在这里插入图片描述
我们可以看到,使用auto关键字,编译器自己推导变量类型。在使用auto时,必须对其初始化,编译器在编译阶段需要根据初始化表达式来推导实际类型,所以auto并不是一种类型的声明,而是一个类型声明的占位符。

auto的使用

1、auto与指针引用结合起来使用

int x = 10;
auto px = &x;
auto* ppx = &x;
auto& rx = x;

需要注意的是,使用auto声明引用类型的话,必须在auto后面加上&,指针可以不用。
2、在同一行定义多个变量

auto a = 1, b = 2;
//auto c = 3, d = 4.0  编译出错,c和d的类型不同

在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器就会报错,编译器会根据第一个推导出来的类型来定义其他变量。
3、auto不能作为函数形参类型
4、auto不能直接声明数组。
5、auto与for循环搭配使用

C++11新式for循环

在11中,循环常与auto搭配使用。for循环的条件有冒号分为两部分,第一部分是范围内用于迭代的变量,第二部分是用于迭代的范围

int array[] = {1, 2, 3, 4, 5};
for(auto& a : array){
	a *= 2;
}
for(auto a : array){
	cout << a << " ";
}

与普通循环类似,可以用continue和break来控制循环。

指针控制nullptr

C++11用nullptr来表示控制指针,与之前NULL不同的是,NULL仅仅是一个宏,但是nullptr是有类型的,表示一个指针空值常量。

typedef decltype(nullptr) nullptr_t;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值