函数重载:
定义:在同一作用域中,为了不改变函数名并且不出错,就要对函数进行重载,而C语言并不支持此语法,一个作用域中不能出现同名函数。
重载要求 | 必须要满足第一点,234三者有其一即可 |
---|---|
1 | 函数名必须相同 |
2 | 参数个数不同 |
3 | 参数类型不同 |
4 | 参数类型的次序不同 |
- 函数参数个数,参数类型,参数顺序称为参数列表
- 如果多个同名函数只有返回值类型不同,而参数列表相同不构成重载,
- 因为在底层并没有对返回值类型不同这个条件作为条件指示编译器调用哪个函数。
函数重载举例:
- 上述的两个函数就满足重载条件,编译器会根据其参数调用相应的函数
- 如果没有类型完全合适的函数,则编译器会尝试进行隐式转化,如果有合适函数则调用,没有则报错
在汇编语言中C和C++的函数名字修饰规则不同
C++更复杂,且环境不同时,命名方式也不同(这也就是为什么,C++中函数名相同,但是参数列表不同,语法依旧正确)
将生成的exe程序改成库
exter “C”{}
C++调用C语言写的库时,告诉编译器,里面包含的库是以C语言的方式编译的
内部函数也就不符合C++的语法了
内联函数:
在编译阶段展开
目的:为了提升程序运行的效率
在使用时,在声明和定义处都要加关键字inline
常规函数和内联函数间的主要区别不在于编写方式,而在于C++ 编译器 如何将它们组合到程序中;
常规函数调用:
- 程序执行到函数调用指令时,程序会存储该指令的内存地址,并为开辟一块新内存让函数执行;
- 并将函数参数复制到堆栈中;
- 再跳到标记函数起点的内存单元,执行函数代码;
- 结束后跳回到执行函数调用的指令处;
(这个过程就像在阅读文言文,有的字句有一个脚注标识,我们在阅读的时候去看释义,看完后返回到原来的位置)
内联函数将函数内部代码和其它程序代码结合在一起,程序在执行时遇见内联函数无需将参数复制到堆栈中,无需为函数开辟运行内存空间
内联函数与宏的区别举例
- 显而易见宏和内联函数的实现方式不同(如果相同值就一样),
- 宏是通过文本替换实现,而内联函数依旧是通过传递参数实现;
- 也可以说内联函数是对C语言宏函数的一种优化。
宏不支持调试,比较难懂
没有类型安全检查
内联函数使用注意:
- 内联函数是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。
- 内联函数对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等,编译器优化时会忽略掉内联函数
- 内联函数不建议声明和定义分离,分离会导致链接错误
因为inline被展开,就没有函数地址了,链接就会找不到
定义时候的inline对编译器
auto:
c++98中,auto含义在c和c++中一样自动变量,可自己销毁,在c语言中没有多大作用,变量都能自动的销毁
auto int a=10; //C++98中正确,在C++11中错误
c++11赋予了auto新的含义:
- auto不再是一个存储类型指示符,只是一个占位符,auto声明的变量必须由编译器在编译时期推导而得
- 使用关键字auto而不指定变量类型(auto是一个占位符),编译器将把变量类型设置成与初始值相同(在编译阶段完成类型确定)
1.使用auto一定要初始化
auto d; //错误
---------------------------------
int a=10;
auto b=a; //正确
---------------------------------
auto c=12.34; //将auto替换成double
2.auto定义指针时,auto和auto* 没有任何区别,但是声明引用必须要有&(auto&);
int a=10;
auto* pa1=&a //auto被换成int
auto pa2=&a //都正确auto被换成int* ;pa1和pa2类型一样
-------------------------------------------------
auto ra=a;
ra=100; //打印后a的值不变还是10,ra不是a的引用,ra与a类型相同
auto& ra=a;
ra=100 //a会改变,ra此时是a的引用
上述代码一般情况不会使用,增加编译时间
3.auto在一行定义多个变量时,该行变量的类型应相同
auto只能在一行生效并不能再改变
auto a=1, b=2.0; //错误
4.auto不能作为函数参数
函数在声明时就应指定参数类型,auto可以看做无类型
编译器无法对a的实际类型进行推导,就无法开辟空间给函数参数(函数参数带默认值也不行)
void test (auto a=30) {}; //错误
5.不能声明数组
int arr1[]={1,2,3}; //数组类型是int [3]
auto arr2=arr1;
//编译成功,因为数组名是数组首元素地址,是指针
cout << typeid(arr2).name() << endl;
//输出类型是int*,数组类型是int[3]