C++内联函数/auto/范围for/nullptr

内联函数

首先回顾一下,宏的本质是替换,这就意味着宏的结尾不能用分号

#define ADD(x, y) x + y;

printf("%d", ADD(1, 2));

比如说上面的这种定义,本质是替换,那么printf里面的ADD(1,2)就要被替换为1 + 2;

注意后面还跟了一个分号,这样语句就有问题了

而且当我们遇到这样的场景的时候

#define ADD(x, y) x + y

printf("%d", ADD(1, 2) * 2);

你会发现得出的结果和我们预期的不一样,这是优先级的问题,所以要加上括号

#define ADD(x, y) (x + y)

但是当我们遇到这样的,仍然会出问题

ADD(a | b, a & b);
//相当于 (a | b + a & b)

结果也和我们预期不一样,也是因为优先级

所以我们的ADD替换应该这样写

#define ADD(x,y) ((x) + (y))

在这里插入图片描述

C++开发者,为了解决宏的问题,引出了内联函数的概念

内联函数的概念

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

int add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = add(1, 2);
	return 0;
}

在这里插入图片描述

这是普通函数,要建立栈帧,call就是标志,那么我们来看内联函数

注意在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化

在这里插入图片描述

设置如下

在这里插入图片描述

在这里插入图片描述

内联函数的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:不用建立栈帧,少了调用开销,提高程序运行效率。

在这里插入图片描述

在这里插入图片描述

这就是他的缺点

  1. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。

在这里插入图片描述

​ 如在面对复杂的内联函数时候,编译器会将其当作函数

在这里插入图片描述

3.内联函数的定义和声明不能分开,不然会出现链接错误,因为在定义部分

在这里插入图片描述

编译器觉得没有必要生成指令,将地址放到符号表去,是直接展开的,也可以认为内联函数在符号表里没有地址

在这里插入图片描述

但是我们间接调用就可以,是因为什么?

宏的优缺点?

优点:

  1. 增强代码的复用性。
  2. 提高性能。

缺点:

  1. 不方便调试宏。(因为预编译阶段进行了替换)
  2. 导致代码可读性差,可维护性差,容易误用。
  3. 没有类型安全的检查 。

C++有哪些技术替代宏?

  1. 常量定义 换用const enum
  2. 短小函数定义 换用内联函数

上面是内联函数,下面介绍常量定义用的关键字

关键字auto

  • 在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量
  • C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
  • 通俗来讲就是auto可以自动识别类型
  • auto的作用是可以避免写很长的类型名

在这里插入图片描述

并且可以同过typeid(变量名).name()查看原属类型

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto 的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编 译期会将auto替换为变量实际的类型

范围for

在C++中可以这样遍历数组

在这里插入图片描述

注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

我们使用习惯性的使用auto来自动接收,当然也可以用数组元素类型来接收也行,只是auto更加方便,e只是变量名,意思是将数组里面的值依次赋值给e

在这里插入图片描述

如图,我们是将数组里的值依次给了变量x,变量x的改变不会引起数组的变化

想要做到同时修改,加引用

在这里插入图片描述

想一想,指针行不行?

注意,这种是不行的,因为必须要数组名,这里的形参是指针
在这里插入图片描述

空指针nullptr

nullptr是为了代替NULL使用的,因为NULL在使用的时候有一个大坑

重载函数,原意是第一个f函数匹配第一个,第二个匹配第二个

这是因为NULL本身是一个宏

//NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

可以看到,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦。为了避免修改产生新的错误,干脆直接引用了nullptr关键字来替代NULL

nullptr也是0,不过是void*类型的

注意:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入 的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。

用了nullptr关键字来替代NULL

nullptr也是0,不过是void*类型的

注意:

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入 的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
  3. 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值