• C/C++中的new和delete的实现过程


    文章目录


    下面是《C++ Primer 5th》中P726 对 new 和 delete 过程的解释:

    当我们使用一条new表达式时,实际上执行了三步操作:

    1. new表达式调用一个名为 operator new (或者 operator new[] )的标准库函数。该函数分配一块足够大的、原始的、未命名的内存空间以便存储特定类型的对象(或者对象数组)。
    2. 编译器运行相应的构造函数以构造这些对象,并为其传入初始值。
    3. 对象被分配了空间并构造完成,返回一个指向该对象的指针。

    当我们使用一条delete表达式时,实际上执行了两步操作:

    1. 对sp所指的对象或者arr所指的数组中的元素执行相应的析构函数。
    2. 编译器调用名为 operator delete (或者 **operator delete[] **)的标准库函数释放内存空间。

    由于不同编译器对new的实现过程不同,所以我们下面以侯捷老师课件来进行详解。

    new

    假设我们现在有一个类:complex.h

    #ifndef __MYCOMPLEX__
    #define __MYCOMPLEX__
    
    class Complex {
    public:
    	Complex(double r = 0, double i = 0) :m_real(r), m_imag(i) {}
    	double real() const { return m_real; }
    	double imag() const { return m_real; }
    
    private:
    	double m_real;
    	double m_imag;
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    我们new一个对象

    Complex* pc = new Complex(1,2);//Complex为类名(复数)
    
    • 1

    编译器处理new这一语句的时候,先分配复数的内存,然后进行转型,最后调用构造函数,进行了下面三个过程

    void* men= operator new( sizeof(Complex));//第一步,分配内存
    pc = static_cast<Complex*>(men);//第二步,转型
    pc->Complex :: Complex(1,2);//第三步,调用构造函数
    
    • 1
    • 2
    • 3

    下面是在VS2019上反汇编得到:
    请添加图片描述

    整体示意图如下:

    在这里插入图片描述

    delete

    当我们进行 delete 操作时:

    delete pc;
    
    • 1

    在编译器的处理过程中,这一语句转化两个步骤:先析构再free

    Complex::~Complex(pc);//析构函数
    operator delete(pc);//释放内存
    
    • 1
    • 2

    下面是在VS2019上反汇编得到:
    请添加图片描述

    示意图如下:

    在这里插入图片描述
    整体代码如下:

    int main() {
    
    	Complex* pc = new Complex(1, 2);
    
    	cout << pc->imag() << ":" << pc->real() << endl;
    
    	delete pc;
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    整体程序运行结果如下:
    在这里插入图片描述

    new[]

    假设我们有一个类 MyString.h

    #ifndef __MYSTRING__
    #define __MYSTRING__
    
    #include <string>
    
    class MyString {
    public:
    	MyString(const char* cstr = 0) {
            if (cstr) {
                m_data = new char[strlen(cstr) + 1];
                strcpy(m_data, cstr);
            }
            else {
                m_data = new char[1];
                *m_data = '\0';
            }
    	}
        ~MyString() {
            delete[] m_data;
        }
        char* get_c_str() const { return m_data; }
    private:
        char* m_data;
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    我们new一个对象

    MyString* ps = new MyString("Hello");
    
    • 1

    编译器处理new这一语句的时候,也是分为三个过程,与上相同

    void* men= operator new( sizeof(MyString));//第一步,分配内存
    ps = static_cast<MyString*>(men);//第二步,转型
    ps->MyString:: MyString("Hello");//第三步,调用构造函数
    
    • 1
    • 2
    • 3

    下面是在VS2019上反汇编得到:

    请添加图片描述
    示意图如下:
    在这里插入图片描述

    delete[]

    当我们进行 delete 操作时:

    delete ps;
    
    • 1

    在编译器的处理过程中,这一语句转化两个步骤:先析构再free

    MyString::~MyString(ps);//析构函数
    operator delete(ps);//释放内存
    
    • 1
    • 2

    下面是在VS2019上反汇编得到:

    请添加图片描述

    请添加图片描述

    示意图如下:

    在这里插入图片描述

    整体代码如下:

    int main() {
    
    	MyString* ps = new MyString("Hello");
    
    	cout << ps->get_c_str() << endl;
    
    	delete ps;
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    整体程序运行结果如下:
    在这里插入图片描述

  • 相关阅读:
    Web大学生网页作业成品——易购商城网站设计与实现(HTML+CSS+JavaScript)
    贪心,队列,运算符重载,牛客:连环爆炸
    自媒体怎么入门?过来人的三点建议,快看看
    dubbo启动之注册中心(Registry)
    css第一课:css内部样式
    C++入门5 名字空间|new|虚拟地址
    32、多租户(multi-tenancy)
    mongo加入systemctl进行管理服务
    【限时免费】20天拿下华为OD笔试之【哈希集合】2023B-明明的随机数【欧弟算法】全网注释最详细分类最全的华为OD真题题解
    光学:薄透镜成像、景深
  • 原文地址:https://blog.csdn.net/qq_43142509/article/details/125446938