1、调用约定
_cdecl: C标准调用约定
- 从右至左的顺序将参数压入栈中
- 形参的开辟由调用方处理,清理由调用方处理
- 编译后的函数名前加一个下滑线,如:_fun
_stdcall:windows下标准调用约定
- 从右至左的顺序将参数压入栈中
- 形参的开辟由调用方处理,清理由被调用方处理
- 编译后的函数名前加一个下滑线,函数名后面加一个@,如:_fun@
_fastcall:快速调用约定,通过寄存器传递参数,相比较取内存栈中读取参数,该调用约定更快
- 使用ecx和edx寄存器传递前两个参数,其他参数从右至左的顺序将参数压入栈中
- 形参的开辟由调用方处理,清理由被调用方处理
- 编译后的函数名前后个加一个@,并且在后面紧跟函数参数的字节数如:@fun@8
_thiscall:类成员方法缺省的调用约定
2、C与C++区别
1、函数重载
静多态包含函数重载和函数模板,多态是为了实现接口服用,它可以用8个字概括:同一接口,不同形态,是函数的形参为函数重载提供支持。重载的三要素是:同名、同作用域、不同参。(调用点看不见返回值类型)
C语言中产生函数符号的规则根据函数名产生,所以c语言中不存在函数重载。C++中产生函数符号的规则根据函数名、参数个数、参数类型。
2、new和malloc的区别
1、属性:new/delete是C++的关键字,需要编译器的支持;malloc/free是库函数,需要头文件的支持
2、参数:new在申请内存分配时无需制定内存块的大小,编译器会在根据类型信息自行计算;malloc需要显式的置处所需内存的大小
3、返回类型:new分配成功时,返回的时对象类型的指针,类型严格与对象匹配,无需进行类型转换,符合类型安全;malloc分配成功返回void*,需要通过强制类型转换将void*转换成我们需要的类型
4、分配失败:new会抛出bac_alloc异常;malloc返回NULL
5、自定义类型:new先调用operator new函数,申请足够的内存(通常底层使用malloc实现),再调用类的构造函数,初始化对象的成员变量,最后返回自定义类型指针;malloc是库函数,只能申请内存,不能进行初始化
6、重载:new可以重载,因为operator new可以重载,所以new可以调用malloc;malloc不可以重载,所以malloc不可以调用new
7、内存区域:new在自由存储区;malloc在堆上(在C中,内存分为:堆、栈、全局/静态、常量存储区。在C++中,内存分为:堆、栈、自由存储区、全局/静态、常量存储区)
8、new可以开辟常量,如:const int *p = new const int(20);;malloc不可以
eg:int *p = new int[10];delete p;程序不会出错,地址匹配上了。Test *t = new Test[10];delete t;当自定义类型用new申请数组,只释放一个,程序会中止、出错,因为使用new申请10个对象时,每一个对象不光申请了空间,而且都调用一次构造,而只释放一个对象只调用了一次析构
9、使用malloc分配的内存后,如果在使用过程中发现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩充。realloc先判断当前的指针所指内存是否有足够的连续空间,如果有,原地扩大可分配的内存地址,并且返回原来的地址指针;如果空间不够,先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来的内存区域。而new没有这样直观的配套设施来扩充内存。
10、C++提供了new[]和delete[]来专门处理数组类型,使用new[]分配的内存必须使用 delete[]进行释放。new[]一次分配所有的内存,多次调用构造函数,搭配使用delete[],delete[]多次调用析构函数,销毁数组中的每个对象。而malloc则只能手动自定数组的大小。
3、const
在C语言中,const修饰的变量称为常变量,是global属性。在编译阶段看常变量是否做左值,其他处理和普通变量一样
在C++中,const修饰的变量称为常量,是local属性,可以使用extern去掉local属性。在编译阶段处理把用到常量的地方直接替换常量初始化的值。
- 一定要初始化
- 常量不能做左值
- 不能间接修改,杜绝间接访问来修改常量内存的风险(如果用普通指针指向const修改的变量,普通指针一定会解引用,所以存在风险)
const修饰指针变量(函数参数)时:
1.只有一个const,如果const位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,可以指向其他的内存单元。
2.只有一个const,如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址;指针所指的数据可以通过解引用修改。
3.两个const,*左右各一个,表示指针和指针所指数据都不能修改。
const修饰成员函数:
1.const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外)
2.const成员函数不能调用非const成员函数,因为非const成员函数可以会修改成员变量
this指针是Test *const this = &test
4、inline函数
在编译阶段,调用点展开,所以导致只能本文件可见
inline函数和static修饰的函数的区别:inline函数没有开栈清栈的开销,因为在编译阶段代码展开导致inline函数只能本文件可见;static修饰的函数除了因为符号属性为local属性,所以只能本文件可见之外其他和普通函数没什么区别
inline函数和宏函数的区别:inline函数在编译阶段处理,所以它有类型检查和安全检查,宏函数是在预编译阶段进行的文本替换,没有类型检查和安全检查。inline是一种更安全的宏
inline注意事项:
- inline函数一般写在头文件中
- inline只在Release版本下生效
- inline是给编译器的一个建议,递归、循环、switch都不能写成inline
- inline函数是基于实现的,而不是基于声明的
- inline函数是以代码膨胀为代价,用空间换时间
5、函数默认值
- 自右向左依次赋值
- 不能重复赋值
- 一般写在声明上
6、C和C++的相互调用
C++调用C时:C++中写extern "C"
C调用C++时:当可修改C++源文件时,在C++源文件添加extern "C";当不可修改C++源文件时,加.cpp文件当中间层
当编译.C文件时,不知道编译器的编译方式:加宏#ifdef_cplusplus
7、namespace,存在同名的namespace会合并
using namespace std; using指示符
using std::cout; using声明