目录
❤️前言
大家好!今天要和大家一起学习的内容是一些从C语言到C++的一些新特性和知识,包括C++中的内联函数、auto关键字、基于范围的for循环、以及新关键字nullptr的知识。
正文
我们首先一起来了解关于内联函数的知识。
内联函数
我们都知道,当我们调用一个一般的函数,编译器在处理函数的调用指令时会在内存中的栈区上建立函数栈帧,此时会产生一定的时间开销,那么我们在C语言中是如何去解决这个问题的呢?当时我们是用使用预处理指令define去声明一个宏函数的方法来处理这个问题,当编译器对一段代码进行编译时,它会在预处理阶段将宏函数以当初声明出的形式完全的替换进它所处的地方,这会造成一些问题。
比如说当我们写一个简单的两数相加的宏函数:
// 我们需要在这个函数中加入许多括号保证不会发生运行错误
#define ADD(x,y) ((x)+(y))
// 注意宏函数会将x和y的表达式直接替换进原位
// 将x、y以括号括起来,这样的话就可以防止传入表达式所造成的意义不明确
所以说,我们在使用宏函数时会产生一些麻烦的问题,而且当宏函数出错时,我们难以进行调试和维护。
那么此时C++就创造了内联函数这个特性,编译时编译器会将内联函数直接在调用处展开函数体,而不会产生调用指令,以此来减少函数栈帧的创建次数,从而提高运行效率。
// 以两数相加作为例子进行演示
// 使用时只要在定义前加上一个关键字 inline即可
inline int Add(int a, int b)
{
return a+b;
}
内联函数是一种以空间换时间的做法,虽然能提高效率,但是可能会使生成的文件变大(函数直接在调用处展开),为此C++规定inline只是我们对于编译器的一种请求,是否采纳是编译器内部自己决定的,所以我们在定义内联函数时要保证函数的规模较小。除此之外,内联函数不能是递归调用的,并且应该是频繁使用的函数,否则编译器可能会忽略inline的特性。
最后一点,内联函数的定义和声明不可以分离,因为当函数直接在调用处展开,这个函数就没有相对应的地址,我们可以直接在自己使用的头文件中定义内联函数,这样的话,编译时头文件中的内容会自动拷贝到所有引用此头文件的源文件中,这样就很方便于我们的使用了。
auto关键字
随着我们写的程序越来越复杂,我们在程序中使用到的类型也越来越复杂,这时候C++11就给出了auto这一个类型指示符,它可以自动推导出初始化表达式的类型,那么我们在使用较为复杂的类型时便可以以auto来代替编写。
注意:使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类 型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为该变量实际的类型。
使用规则:
- 当我们将auto和指针、引用类型结合在一起使用时,auto和auto*没有区别,但是auto在声明引用类型时需要加上&。
- 在同一行使用auto声明多个变量时,必须保证这些变量的类型一致,否则编译器将会报错。
- auto不能作为函数参数,因为这样的话编译器无法对该参数的实际类型做出推断
- auto不能用于数组声明
基于范围的for循环
对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中 引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量, 第二部分则表示被迭代的范围。
例如说我们用范围for循环遍历一个数组:
int arr[] = { 0,0,0,0,0,0,0,0 };
for (int& x: arr)
{
cout << x << " ";
}
cout << endl;
for (int& x : arr)
{
x++;
}
for (auto& x : arr)
{
cout << x << " ";
}
// 代码的运行结果:
// 0 0 0 0 0 0 0 0
// 1 1 1 1 1 1 1 1
在使用范围for时需要保证这个范围时明确的,对于上述的数组,此范围就是数组的开始到结束。
指针空值nullptr
当我们声明指针变量时,最好将它们初始化,如果没有准确的指向,我们常常会将这个指针初始化为NULL,但是NULL其实是一个宏,在使用时可能会被定义为0或者是无类型的指针常量,这时候可能就会产生一些问题。那么C++11便引入了一个新的关键字nullptr作为指针空值,如果我们以nullptr作为指针空值去初始化指针变量则不会发生NULL产生的问题,因此我们后续使用指针空值时最好使用nullptr以提高代码的健壮性。
🍀结语
到这里我们就结束了今天的学习分享,而且对于C++入门知识的分享这里也暂时告一段落,最后希望看到这里的大家能够学习进步,天天向上!