operator new和operator delete函数
定义: operator new和operator delete是系统提供的全局函数;用法与malloc和free相同,功能都是在堆上申请、释放空间;
int* p1 = (int*)operator new (siaeof(int));
operator delete(p1);
- operator new实际上是通过malloc来申请空间的,申请成功时直接返回,失败时,会尝试执行空间不足应对措施,若该应对措施用户设置了,则继续申请,否则抛异常;
- operator delete实际上是通过调用free释放空间。
注:
malloc和operator new用法一样,但是申请空间失败后的方式不一样:malloc失败后返回NULL,operator new失败后抛异常。
new和delete的实现原理
针对内置类型:
- new、delete和malloc、free申请空间基本相似;
- 不同之处在于:new、delete申请、释放的是单个元素空间,new[]、delete[]申请释放的是连续空间;申请空间失败时,malloc返回NULL,operator new抛异常。
针对自定义类型:
- new:调用operator new函数申请空间,在申请的空间上执行构造函数,完成对象的构造;
- delete:在空间上执行析构函数,完成对象中资源的清理工作,调用operator delete函数释放对象的空间;
- newT[N]: 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请,在申请的空间上执行N次构造函数;
- delete[]: 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理,调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。
小结malloc/free和new/delete:
- 都是在堆上申请空间,需要用户手动释放空间;
- malloc/free是函数,new/delete是操作符;
- malloc申请的空间不会初始化,new申请的可以初始化;
- malloc申请空间时,需要手动计算空间大小传递给(sizeof),new只需要在后面跟上空间类型即可,如果是多个对象,需要在[]中指定对象个数;
- malloc返回值为void*,使用时必须进行类型强转;new不需要强转(因为new后直接跟的就是类型);
- malloc申请空间失败时返回NULL,使用时必须判空,new不需要判空,它申请失败时会抛异常;
- 申请自定义对象时,malloc、free只会开辟空间和释放内存;new还会在申请空间之后调用构造函数完成初始化,delete会在释放空间之前调用析构函数完成空间中的资源清理。
内存泄漏
定义:
- 指因为疏忽或错误造成内存未能释放,从而不能再去使用该段内存的情况;
- 内存泄漏并不是指内存在物理上的消失,而是失去了对该段内存的控制(可以理解为是指针丢了,不是内存丢了),造成了内存空间浪费。
危害:会导致操作系统、服务器等反映越来越慢,最终可能会卡死。
泛型编程
定义: 泛型编程指编写与类型无关的通用的代码,是代码复用的一种手段,模板是泛型编程的基础。
- 模板分为:函数模板、类模板。
函数模板
定义: 函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,能根据实参类型产生函数的特定类型版本。
函数模板格式:
template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}
template <class T>;
void my_sawp(T& x1,T& x2)
{
T tmp = x1;
x1 = x2;
x2 = tmp;
}
注:定义模板T,既可以使用template,也可以使用class。
函数模板的实例化:
- 函数模板的实例化是指根据不同类型的形参,调用的是不同类型的函数;
- 隐式实例化:编译器会通过实参推形参的类型T分别为哪种;
- 显式实例化:不让编译器推演类型,显式指定类型(实参类型不一致)。当实参类型不一致时,可在调用函数名后加<>,里面表示类型(即告诉编译器去调用哪个函数)。
模板参数的匹配原则:
-当 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数,则与非模板函数匹配,编译器不需要特化;
- 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板;
- 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。
类模板
定义格式:
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
类模板的实例化 :
类模板实例化与函数模板实例化不同,实例化需要在类模板名字后跟<>,再将实例化的类型放在<>中,注意:类模板名字不是真正的类,而实例化后的结果才是真正的类。