目录
内联函数的提出
C++推荐用const和enum来替代宏常量,用inline去替代宏函数
宏函数缺点:
不能调试
有些条件下非常复杂,不易掌握
直接替换,无法检测类型安全
我们可以先实现一个简单的加法宏函数
可以看出宏函数的构造十分复杂,加括号的目的是为了使运算更加安全,此处我们测试宏函数所以不多赘述。
这里使用宏函数有两个优势:
1.不用开辟栈帧,节约空间
2.可以接收多种类型的数据,比如int 、double
接下来我们用内联函数重写Add函数
inline int Add(int x, int y)
{
int z = x + y;
return z;
}
需要注意的是,编译器的debug版本内联需要配置才能起作用,release版本下内联也会起作用。具体配置方法,这样就对Add这个函数进行了一个优化。
内联的特点
inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
用函数体替换函数调用。缺陷:(编译出来的可执行程序变大)优势:少了调用开销,提高程序运
行效率。因为函数调用是直接去call这个函数的地址进行函数栈帧的开辟,调用完成后就会销毁,而内联函数虽然优化了一些函数调用操作,但却都实实在在地写入到了程序中。
内联函数只是一种对编译器的建议,如果你调用了写了100行代码的1000次inline,你就会得到100000行代码,这时编译器就会制止你愚蠢的行为。
对于优化规模较小,流程直接,频繁调用的函数,请使用内联。(不要用递归)
声明和定义不能分离
//test.h
inline int Add(int x, int y)
//test.cpp
#include"test.h"
inline int Add(int x, int y)
{
int z = x + y;
return z;
}
//主程序
#include"test.h"
int main()
{
Add(1,2);
return 0;
}
分离后会出现链接错误,这是因为inline是优化后的函数,他不会去调用函数栈帧,自然在链接过程中无法找到函数地址,即无法链接上test.cpp的内容,因为就没有产生相应的符号表。
所以推荐直接在.h文件定义。
auto函数
auto即自动推导函数
auto a = 2;
auto b = 2.4;
auto c = &a;
这里我们用“typeid”这个函数来识别它们的类型
//推导函数返回值
inline int Add(int x, int y)
{
int z = x + y;
return z;
}
auto d = Add(1, 2);
cout << typeid(d).name() << endl;
自然,auto的好处在后面的学习中会代替一些比较复杂的类型比如说迭代器等,方便简化代码。
typedef缺点
随便提一下,假设类型名很长也可以用typedef来定义,但是却没有auto来得方便,毕竟,术业有专攻。下面是一个typedef缺陷的代码例子
typedef int* ptr;
const ptr p;
const ptr* pp;
哪一个对,哪一个错?或者都对?
答案是第一个错误,第二个正确。因为在未执行预处理操作替换时,const是修饰p的,一旦替换进去,就成了int* const ptr了,我有一篇文章区分过const位置代表什么意思,这代表这常量指针,特点是必须初始化一个值,因为不能修改指针指向的地址。
一些特点
auto* c = &a;
auto& d = a;
我们注意一下这样使用的时候赋值对象是否正确,否则就会报错,并且指针类型是可以直接被auto推断出来的,可以根据可读性自行添加,而引用类型就是给这个对象取别名,使推到类型增加引用属性。
auto的语法糖功能
两组代码对比分析,可以理解为下面的方式是对上面的一种简化,原理是自动依次取数组中数据赋值给x对象,自动判断结束。
除此之外,若想改变数组的值,只需在auto后加上&就行了,这样从单纯的赋值变成了数组每个值的别名,实现修改操作。
特殊情况
void f(int arr[])//指针
{
for (auto& x : arr)
{
cout << x << " ";
}
}
将auto放入函数中推导是不行的,因为传过来的不是整个数组,而是数组首元素地址。
auto支持同时初始化多个参数,但参数类型必须一致
auto a = 3,b = 4.0//错误
auto c = 1,b = 2;
auto不能做形参,个人理解是避免与函数重载混淆
auto不能声明数组,因为可能会出现内部成员不一致的情况。
总之,auto是把双刃剑,得合理运用。
c/c++空指针问题
我们知道,c得空指针是NULL,到了c++,NULL出现了一些问题,被替换成了整数0。
C++11 引入了 `nullptr` 关键字,以替代原来用于表示空指针的整数常量 `NULL` 或 `0`。`nullptr` 有明确定义的类型,可以更安全地用于类型推断和函数重载解析。
使用 `nullptr` 还可以避免一些令人困惑和易错的问题。例如,如果将整数常量 `0` 与指针进行比较,则编译器将隐式地将其转换为指针类型,这可能会导致无意中匹配错误类型的重载函数。而通过使用 `nullptr`,可以避免这种问题,因为它只能被隐式转换为指针或成员指针类型,不会转换为整数类型。
这就是c++的预备知识了,接下来我们学习c++的类和对象吧。