用inline修饰的函数叫做内联函数
没有函数压栈的开销,提高了程序的运行效率
频繁调用
宏
比如频繁调用Add函数
#define ADD(x,y) ((x)+(y))
宏的本质就是替换,预处理时会进行宏的替换,温馨提示/doge:定义宏时多加括号
宏的缺点:
不利于调试,在预处理阶段替换完成了,调试时直接看到替换后的结果
可读性差,维护性差,容易出错
没有类型安全的检查
宏的优点:
- 代码复用性增强
- 提高了性能(调用函数需要开辟栈帧之类的)
由于宏的不足,C++推荐用const、内联函数替代宏
其中const 常用来定义常量 函数定义换成内联函数
不用开辟栈帧,在调用处直接展开函数
内联函数本质上是时间换空间
代码过长,有循环,有递归等都不适合用递归(编译器会检查,如果代码过长就算用inline修饰了也会当作没修饰一样去编译),此时编译器会忽略掉内联
内联函数一般是1-5行,编译器会自动优化,因为太长会导致代码膨胀,花费的空间过多
内联函数的声明和定义放一起,不然容易出现链接错误
-----test.h-----
#include
using namespace std;
inline int Add(int x, int y);
-----test.cpp-----
#include"test.h"
int Add(int x, int y)
{
return x + y;
}
-----main.cpp-----
#include"test.h"
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
运行结果:
error LNK2019: 无法解析的外部符号 "int __cdecl Add(int,int)" (?Add@@YAHHH@Z),该符号在函数 _main 中被引用
原因是被inline修饰过后链接属性变化
链接属性:external,inline,none等,感兴趣可以百度了解
#include
using namespace std;
inline int Add(int x, int y)
{
return x + y;
}
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
一个类型(指示符),auto可以让编译器会自动推导变量的类型
比如 auto a=1;编译器在编译时期推导出a为int类型
(auto 通过赋值对象自动推导类型)
必须初始化
编译器才好推导类型
auto 推导指针时auto和auto*是一样的,但是声明引用时必须加&
#include
using namespace std; int main() { int a = 1; auto pa = &a; auto* pa2 = &a; auto& b = a;//b是a的别名 cout << typeid(pa).name() << endl; cout << typeid(pa2).name() << endl; cout << typeid(b).name() << endl; return 0; }
auto不能用来作参数和数组声明
假如auto去修饰形参,那变量应该开多大的空间存储?
所以肯定不能作参数,数组同理
auto同一行声明的多个变量需要是同种类型
auto a=1,b=2; 可行,因为类型相同
提供了一种新的访问数组的方式
#include
using namespace std;
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
for (auto e : arr)
{
cout << e <<" ";
}
cout << endl;
return 0;
}
用范围for把数组的每个元素乘以二
C++98把NULL定义为常量0,C++建议用nullptr表示空指针
NULL是一个宏
nullptr等价于 ((void *)0?
nullptr与指针并不等价,nullptr的类型为nullptr_t,可隐式转换为任何一种指针类型
小结:nullptr既不是整形也不是指针,只是可隐式转换为指针
源码:
stddef.h
#ifdef __cplusplus
namespace std { typedef decltype(__nullptr) nullptr_t; }
using ::std::nullptr_t;
#endif /* __cplusplus */
这里也说明了nullptr并不是指针类型
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else /* __cplusplus */
#define NULL ((void *)0)
#endif /* __cplusplus */
#endif /* NULL */
其中__cplusplus是一个宏(本质上还是一个值);
上述源码的意思简要概括为:如果是C++,NULL就给成0,如果是C,就给成 ((void *)0)
借一个评论区大佬的话说:C++只有在“迫不得已的情况下才会把nullptr隐式转换成指针类型”
C++98把NULL看成0造成了一些麻烦,比如
void func(int)
{
cout << "void func(int)" << endl;
}
void func(int*)//重载
{
cout << "void func(int*)" << endl;
}
void func2(void*)
{
cout << "void func(void*)" << endl;
}
int main()
{
func(NULL);
func(nullptr);
func2(nullptr);
}
评论区的大佬还提到内存管理时delete nullptr更加安全,在此感谢两个大佬的指正
一开始以为nullptr就是个指针
nullptr的类型不是指针,但是在“迫不得已”的情况下会隐式转换成指针
即nullptr可以转成指针,指针不一定可以转化成nullptr
C++会把NULL看成0
C语言里的NULL是((void*)0),一个指针指向内存0x00000000,这块内存不放有效数据
~~ 类与对象内容较多 打算单独记录~~