operator new和operator delete函数、new和delete的实现原理、内存泄漏、泛型编程、模板

本文详细介绍了C++中的`operator new`和`operator delete`函数,以及它们与`malloc`和`free`的区别。接着探讨了`new`和`delete`操作符在内置类型和自定义类型中的实现原理,强调了内存泄漏的危害。此外,还深入讲解了泛型编程的概念,包括函数模板和类模板的应用及实例化规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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抛异常。

针对自定义类型:

  1. new:调用operator new函数申请空间,在申请的空间上执行构造函数,完成对象的构造;
  2. delete:在空间上执行析构函数,完成对象中资源的清理工作,调用operator delete函数释放对象的空间;
  3. newT[N]: 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请,在申请的空间上执行N次构造函数;
  4. delete[]: 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理,调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。

小结malloc/free和new/delete:

  1. 都是在堆上申请空间,需要用户手动释放空间;
  2. malloc/free是函数,new/delete是操作符;
  3. malloc申请的空间不会初始化,new申请的可以初始化;
  4. malloc申请空间时,需要手动计算空间大小传递给(sizeof),new只需要在后面跟上空间类型即可,如果是多个对象,需要在[]中指定对象个数;
  5. malloc返回值为void*,使用时必须进行类型强转;new不需要强转(因为new后直接跟的就是类型);
  6. malloc申请空间失败时返回NULL,使用时必须判空,new不需要判空,它申请失败时会抛异常;
  7. 申请自定义对象时,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 类模板名
{ 
  // 类内成员定义
};

类模板的实例化 :
类模板实例化与函数模板实例化不同,实例化需要在类模板名字后跟<>,再将实例化的类型放在<>中,注意:类模板名字不是真正的类,而实例化后的结果才是真正的类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值