半小时掌握C++之new和delete

150 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

new和delete概叙

C++是一门面向对象的高级语言,在我们编写代码中,常常离不开对对象的创建和清理对象资源。而兼容过来的malloc和free并不能很好的满足我们的需求,从而C++将malloc和free封装起来并起了新的名字new和delete,这两个关键字的作用不仅比malloc和free的功能强大 new和delete都是运算符,不是库函数,不需要单独添加头文件

malloc和free不会对我们自定义类型完成初始化和资源的清理,而new可以完成对象的初始化和delete可以完成对象的资源清理。

new:malloc买地,构造函数建房

delete:析构函数销毁房子,free回收地

//申请空间
int* ptr = new int;
//申请空间并初始化
int* ptr2 = new int(1);
//申请连续的空间,空间大小为4*10=40
int* arr = new int[10];
​
//释放单个空间
delete ptr;
delete ptr2;
//释放连续的多个空间
delete[] arr;

new和delete过程

A *pa = new A();
    operator new(); //函数
        malloc();    //买地,c风格函数分配内存
    A::A();         //建房
    
delete pa;
    A::~A();        //拆房
    operator delete(); //函数
        free()      //回收地,c风格函数释放内存

malloc和free

void* malloc(size_t size); 
void free(void *ptr);

malloc参数size为要分配的字节数,返回值是void*,通常要强转为我们需要申请空间的类型,开辟成功回返回空间首地址,失败会返回NULL,但是申请成功后并不进行初始化,每个数据都是随机值。

int *p = NULL;
p = (int*)malloc(sizeof(int));
*p = 5;
cout<<*p<<endl;
free(p);

怎么自己写operator new函数

operator new函数干了啥?

1、买地malloc

2、在地上画格局线(类型转换)

#include<bits/stdc++.h>
using namespace std; 
​
class A
{
public:
    static void* operator new(size_t n);
    static void operator delete(void* ptr);
    A(){
        cout << "类A的构造函数执行了" << endl;
    }
    ~A(){
        cout << "类A的析构函数执行了" << endl;
    }
    
};
void* A::operator new(size_t size)
{
    cout << "类A的operator new函数执行了" << endl;
    A* ppoint = (A*)malloc(size);
    return ppoint;
}
​
void A::operator delete(void* ptr)
{
    cout << "类A的operator delete函数执行了" << endl;
    free(ptr);
}   
​
int main()
{
    A* pa = new A();
    delete pa;
    cout<<"------------"<<endl;
    A* pa1 = ::new A();
    ::delete pa1;
    return 0;
}
/*
类A的operator new函数执行了
类A的构造函数执行了
类A的析构函数执行了
类A的operator delete函数执行了
------------
类A的构造函数执行了
类A的析构函数执行了
*/

不加::时,调用new会调用类自己定义的operator new方法

加::时,表示调用全局的new和delete方法

static void* operator new(size_t n); static void operator delete(void* ptr);

类的函数,不占用类的空间,不保存在类的对象里面

new一个对象的结构

编译器为了有效地管理内存的分配和回收,肯定会在分配一块内存之外额外分配出许多空间保存更多的信息,编译器最终把分出去的一大块内存中间的某个位置的指针返回给ppoint,作为程序员能使用的内存的起始地址。

#include<bits/stdc++.h>
using namespace std; 
​
class A
{
public:
    static void* operator new[](size_t n);
    static void operator delete[](void* ptr);
    A(){
        cout << "类A的构造函数执行了" << endl;
    }
    ~A(){
        cout << "类A的析构函数执行了" << endl;
    }
    
};  
​
void* A::operator new[](size_t size)
{
    cout << "类A的operator new[]函数执行了" << endl;
    cout << "size: " << size << endl;
    A* ppoint = (A*)malloc(size);
    return ppoint;
}
​
void A::operator delete[](void* ptr)
{
    cout << "类A的operator delete[]函数执行了" << endl;
    free(ptr);
}
​
int main()
{
    A* pa2 = new A[3];
    delete[] pa2;
    return 0;
}
/*
类A的operator new[]函数执行了
size: 11
类A的构造函数执行了
类A的构造函数执行了
类A的构造函数执行了
类A的析构函数执行了
类A的析构函数执行了
类A的析构函数执行了
类A的operator delete[]函数执行了
*/

一次把地买好,再修三个房子

3*1=3

有8个地址保存信息

operator new[]函数

#include<bits/stdc++.h>
using namespace std; 
​
class A
{
public:
    static void* operator new[](size_t n);
    static void operator delete[](void* ptr);
    A(){
        cout << "类A的构造函数执行了" << endl;
    }
    ~A(){
        cout << "类A的析构函数执行了" << endl;
    }
private:
    int i;  
};  
​
void* A::operator new[](size_t size)
{
    cout << "类A的operator new[]函数执行了" << endl;
    cout << "size: " << size << endl;
    A* ppoint = (A*)malloc(size);
    cout << "类A的operator new[]函数中返回的首地址" << ppoint<< endl;
    return ppoint;
}
​
void A::operator delete[](void* ptr)
{
    cout << "类A的operator delete[]函数执行了" << endl;
    free(ptr);
}
​
int main()
{
    A* pa2 = new A[3];
    cout<<"程序员能用的首地址"<<pa2<<endl; 
    delete[] pa2;
    return 0;
}
/*
类A的operator new[]函数执行了
size: 20
类A的operator new[]函数中返回的首地址0xc614f0
类A的构造函数执行了
类A的构造函数执行了
类A的构造函数执行了
程序员能用的首地址0xc614f8
类A的析构函数执行了
类A的析构函数执行了
类A的析构函数执行了
类A的operator delete[]函数执行了
*/

3*4=12

有8个地址保存信息