内联函数 auto关键字 基于范围的for循环 指针空值nullptr

一、内联函数(inline)

被inline修饰的函数,会在被调用处展开,没有建立函数栈帧。这一点和C中的宏函数一致,但为什么C++又要再增加inline呢?

我们先来看看宏有哪些的不足吧!

1、代码复杂 可读性低,容易写错

2、无法调试,没有类型安全检查(这是因为宏在预处理阶段就已经被替换掉了)

实际上,其最大的缺点就是第一个,由于宏本质上只是替换,所以它十分容易产生错误,我列举几个常见的错误。

#define ADD(x,y) x+y
int main()
{
	int ret = 3*ADD(3, 4);
	printf("%d", ret);
	return 0;
}

 我们定义了一个简单的相加宏函数,最后输出ret,按照我们习惯,ret应该输出的是21。

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第1张图片

 结果是13,这是为什么呢?本质就是因为宏是个替换,经过替换后ret的右侧变成 3*3+4,这就不难看出答案是13。这告诉我们宏的外侧应该带上括号。

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第2张图片

 

但这样就够了吗?

再看看这样的场景:

#define ADD(x,y) (x+y)
int main()
{
	int x = 1;
	int y = 1;
	int ret = ADD(x&y, x|y);
	printf("%d", ret);
	return 0;
}

 按我们的理解,答案应该是2。

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第3张图片

 很抱歉再次让大家失望了。为了阐释这个原因,我们再来看看宏替换后的结果。

应该是1&1+1|1,注意到+的优先级是远高于逻辑与和或的优先级。所以最后的结果应该是1&2|1,答案是1。

这个例子告诉我们宏代码内部的变量最好也带上括号,为了就是避免运算符优先级的问题。

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第4张图片

 宏还有许多的易错场景,我就不多赘述了,回到我们的主题,为什么要引入inline?

原因就是inline修饰的函数可以避免宏函数的这种情况,因为它直接返回了值。

 inline修饰的函数具有宏函数的优点,但是它没有了栈帧建立的消耗,也避免了宏函数的缺点,这显然是C++发明者对于宏的优化。

下面我们来实现同样的加法函数,分使用inline修饰与不使用inline修饰,看看调用时候的情况是怎么样的!

当我们不使用inline修饰Add:

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第5张图片

从右侧可以看出来Add函数建立了栈帧。

当我们使用inline修饰Add:

内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第6张图片 

对比上面的图,Add函数并没有建立栈帧,而是直接选择在调用的地方展开,确实减少了函数栈帧的消耗。

inline修饰的函数有一些值得注意的地方

1、编译器有权不展开inline修饰的函数,当函数体内部代码太长的时候,编译器往往选择不展开。

2、inline修饰的函数不要定义与声明分离了,会出现链接错误。 因为定义在.cpp文件中声明在.h中 当cpp文件展开.h文件,但是inline修饰的函数被直接展开了,它的地址不会进入符号表当中,所以链接期间就找不到它的地址了。

二、auto修饰的变量

在C++中提供了auto修饰的变量,编译器会自动推导这个变量的类型。

 内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第7张图片

 auto&与auto*后面的&与*没有任何的意思,仅仅只是强调它们是引用和指针类型。

注意:当右侧是指针类型的时候auto*与auto修饰没有区别。

下面给出auto使用的几个注意的点:
1、auto不能够修饰数组

2、auto类型不能作为函数形参

3、如果一行内有多个被auto修饰的变量,要保证类型相同,否则编译器将会报错。

三、基于范围的for循环

我们将介绍C++中遍历一个数组的方法,具体的细节不多介绍。

 内联函数 auto关键字 基于范围的for循环 指针空值nullptr_第8张图片

 四、指针空值nullptr

C++中对于指针空值不再是NULL,而是引入了一个新的关键字nullptr。

由于C++需要兼容C,原本的NULL并没有被删除,它现在只是一个值为0的宏。

而nullptr的底层实现是将0强转为void*类型使它成为一个指针类型。

你可能感兴趣的:(大数据)