对new/delete的认识

new/delete的认识

回顾:C语言的内存管理

malloc/calloc/realloc/free

  • 函数原型
//返回值:成功:空间首地址,失败:NULL

//malloc 
void * malloc(size_t size);
//size---申请空间的字节数

//calloc(初始化为0)
void *calloc( size_t num, size_t size );
//num---元素个数
//size---每个元素所占字节数

//realloc(对memblock所指向空间进行调整到size个字节)
void *realloc( void *memblock, size_t size );
//memblock---以前分配的内存块的指针
//memblock-->NULL-----与malloc功能类似
//memblock-->!NULL-----newSize
//size---新空间的字节数

//free
void free( void *memblock );
int main()
{
    //malloc,calloc,realloc必须和free成对使用
    int * p1 = (int *)malloc(sizeof(int));
    if(p1 == NULL) //利用返回值可以进行检测
    {
        printf("malloc error\n");
    }
    free(p1);
    int * p2 = (int *)calloc(4,sizeof(int));
    int * p3 = (int *)realloc(p2,sizeof(int)*4);
    free(p3);
    //p2,p3指向的是同一块空间,所以释放p3后不用再释放p2
    
    return 0;
}

new/delete操作符

  • new/delete和new []/delete []
//new/delete 单个元素空间的申请与释放
//new []/delete [] 连续空间的申请与释放

void Test()
{
    int *p1 = new int;  //动态申请一个int类型的空间
    int *p2 = new int(3);  //申请一个int类型的空间并且初始化为3
    int *p3 = new int[5];  //申请5个int类型的空间
    
    delete p1;
    p1 = nullptr;
    delete p2;
    delete[] p3;
}
  • new 与 malloc 的区别
特征new/deletemalloc/free
分配内存的位置自由存储区
内存分配成功的返回值完整类型指针void*
内存分配失败的返回值默认抛出异常返回NULL
分配内存的大小由编译器根据类型计算得出必须显式指定字节数
处理数组有处理数组的new版本new[]需要用户计算数组的大小后进行内存分配
已分配内存的扩充无法直观地处理使用realloc简单完成
是否相互调用可以,看具体的operator new/delete实现不可调用new
分配内存时内存不足客户能够指定处理函数或重新制定分配器无法通过用户代码进行处理
函数重载允许不允许
构造函数与析构函数调用不调用

要注意的地方

  • malloc/new/new[] | free/delete/delete[]
class Test
 {
 public:
 	Test()
 	{
 		cout << "Test():" << this << endl;
 	}
 
 	~Test()
 	{
 		cout << "~Test():" << this << endl;
 	}
 
 	int _data;
 };
 
 int main()
 {
 	printf("malloc!--------\n");
	Test* p1 = (Test*)malloc(sizeof(Test));
	free(p1);
	p1 = NULL;
	
	printf("new!--------\n");
	Test* p2 = new Test();
	delete p2;

	printf("new[]!--------\n");
	Test* p3 = new Test[10];
	delete[] p3;

 	return 0;
 }

 

  1. malloc 不会调用构造函数,free不会调用析构函数
  2. new 回调用类型的构造函数,delete释放堆内存时会调用析构函数(清理对象中资源,空间释放)
  3. new[] 申请空间N*sizeof(T)+调用N次构造函数,delete[]将N个对象从后往前清理,调用N次析构函数,释放空间

operator new/operator delete

new T:申请空间时new是C++提供的操作符(关键字),不是真的函数

operator new 和operator delete是系统提供的 全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

new:
    1.申请空间
    void* operator new(size_t size)
    //size申请空间字节数
    {
        while(NULL == (p = malloc(size)))
        {
            //检测是否提供空间不足的应对措施
            //提供:执行应对措施
            //未提供:抛出异常
        }
        return p;
    }
    2.调用构造函数T()

delete:
    1.调用析构函数:清理对象中的资源~T()
    2.释放空间:
    void operator delete(void* p);
    //该函数是通过free来释放空间的
    
new[]:
    1.申请空间(必须是缺省的构造函数)
    void* operator new[](size_t size = N*sizeof(T)+4);
    //4:用于存放N这个数字,取决于T类是否提供析构函数
    //operator new[]中实际调用operator new函数完成N个对象空间的申请
    2.构造N个对象
    在申请的空间上执行N次构造函数
    
delete[]:
    1.调用N次析构函数:到p空间的前四个字节中取对象个数N,调用N次析构函数,倒着释放
    2.释放空间
    p向前4个字节
  • 这是底层的operator new 的实现
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试
执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
    // try to allocate size bytes
    void *p;
    while ((p = malloc(size)) == 0)
        if (_callnewh(size) == 0)
        {
            // report no memory
            // 如果申请内存失败了,这里会抛出bad_alloc 类型异常
            static const std::bad_alloc nomem;
            _RAISE(nomem);
        }
    return (p);
}

定位new表达式

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

格式:new (place_address) type(initializer-list),place_address必须是一个指针,initializer-list是类型的初始化列表

class Test
{
    public:
    Test()
    : _data(0)
    {
        cout<<"Test():"<<this<<endl;
    }
    ~Test()
    {
        cout<<"~Test():"<<this<<endl;
    }
    private:
        int _data;
};
void Test()
{
       Test* pt = (Test*)malloc(sizeof(Test));
    new(pt) Test;
    //注意:如果Test类的构造函数有参数时,此处需要传参
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值