⭐️ 内联函数
💬 为什么会有内联函数?
内联函数其实是为了弥补 c
的缺陷,比如当我们遇到了一些少量逻辑和代码的情况时,而这些少量的代码又需要被重复使用多次(swap
),我们往往会封装成为一个函数来减少代码的冗余。但是函数在创建和返回的时候存在一些额外的开销,而代码很少执行的速度很快,又由于函数的机制的会导致有一些效率上的问题。所以在 c
中我们一般使用带参宏来解决此场景。
但是宏又是一把双刃剑。宏的缺点: 1.代码长度上宏替换完可能使程序过于的冗余,编译的时候会有一定的开销。 2.会有操作符优先级的问题。 3.宏也没有类型的检查。 4.也不方便调试。 5.还存在一些带有副作用的参数。 宏的优点也很明显,就是执行速度很快,没有函数创建和返回的开销。
所以在 c++
中,引入了 inline
修饰的内联函数来替代宏的方式,编译时 c++
编译器会在条用内联函数的地方展开,没有函数调用时所创建栈帧的开销,内联函数提升了程序运行的效率。
#include <iostream>
using namespace std;
inline void add(int a, int b) {
int c = a + b;
cout << c << endl;
}
int main() {
add(10 , 20);
return 0;
}
ps:
inline
是一种以空间换时间的做法,如果编译器将函数当前内联函数处理,在编译阶段,会用函数体替换函数调用(简而言之就是展开函数内部的代码)。inline
对于编译器只是一个建议,当函数规模较小时,没有递归且频繁的调用采用inline
修饰,否则编译器会忽略inline
特性。inline
函数不建议声明和定义分离,分离会导致链接错误。因为inline
被展开后,就没函数地址了,当链接的时候就会找不到。- 解决方式直接定义即可。
⭐️ auto
关键字
在早期的 c/c++
中 auto
的含义是:auto
修饰的变量是具有自动存储器的局部变量其实本质上就说说明是局部变量。在 c++11
中,auto
定义的变量会推导其类型,编译器在编译期会将 auto
替换为变量实际的类型。
🌠 例1:
#include <iostream>
using namespace std;
int main() {
int n = 10;
auto b = n;
auto d = 10.2;
auto c = 'c';
cout << typeid(b).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(c).name() << endl;
return 0;
}
ps:
typeid(变量).name()
可以打印出变量的类型
auto
还有一些细节上使用的地方,auto*
、auto&
。auto
可以自动识别类型,包括指针类型,而 auto*
强调的是指针类型 auto&
强调的是引用。
🌠 例2:
#include <iostream>
using namespace std;
int main() {
int num = 10;
auto p = #
//auto* p = num; // error
auto* a = #
auto& b = num;
cout << typeid(p).name() << endl;
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
return 0;
}
auto
不可以在一行定义多个变量。auto a = 1 , d = 4.0;
auto
不能作为函数的参数。void Test(auto a);
auto
不能直接用来声明数组。auto arr[] = {1 , 2 , 3};
auto
的使用场景:
- 范围
for
的语法
#include <iostream>
using namespace std;
int main() {
int arr[] = { 1 , 2 , 3 , 4 , 5 };
// 正常遍历
for (int i = 0; i < size(arr); i++) {
cout << arr[i];
}
cout << endl;
// for范围遍历
for (auto val : arr) {
cout << val;
}
cout << endl;
for (auto& val : arr) {
val++;
}
for (auto val : arr) {
cout << val;
}
return 0;
}
ps:
val
是 arr
当前每一个元素的拷贝,改变 val
不会影响到数组的元素。可以采用 auto&
引用的方式,这样 val
就是数组的每一个元素的引用,方便修改。
- 当类型过长的时候可以使用
auto
⭐️ nullptr
关键字
在 c
中 NULL
的本质是 #define NULL ((void*)0)
,但是在 c++
中 NULL
的本质是 #define NULL 0
,这样可能会有一些不可避免的麻烦。新的代替方式是关键字 nullptr
。
ps:
在使用 nullptr
表示空指针时,不需要包含头文件,因为 nullptr
是作为 c++11
的新关键字。