最新C/C++中的new和delete的实现过程小结

目录
  • new
  • delete
  • new[]
  • delete[]

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

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

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

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

  • 对sp所指的对象或者arr所指的数组中的元素执行相应的析构函数。
  • 编译器调用名为 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

我们new一个对象

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

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

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

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

整体示意图如下:

delete

当我们进行 delete 操作时:

delete pc;

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

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

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

示意图如下:

整体代码如下:

int main() {
	Complex* pc = new Complex(1, 2);
	cout << pc->imag() << ":" << pc->real() << endl;
	delete pc;
	system("pause");
	return 0;
}

整体程序运行结果如下:

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

我们new一个对象

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

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

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

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

示意图如下:

delete[]

当我们进行 delete 操作时:

delete ps;

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

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

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

示意图如下:

整体代码如下:

int main() {

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

	cout << ps->get_c_str() << endl;

	delete ps;

	system("pause");
	return 0;
}

整体程序运行结果如下:

到此这篇关于C/C++中的new和delete的实现过程的文章就介绍到这了,更多相关C++ new和delete内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解C++中的new和delete并实现对象池

    深入理解new和delete new和delete称作运算符 我们转反汇编看看 这2个运算符本质也是相应的运算符的重载的调用 malloc和new的区别? 1.malloc按字节开辟内存的:new开辟内存时需要指定类型 new int[10] 所以malloc开辟内存返回的都是void* 而new相当于运算符的重载函数 operator new ->返回值自动转成指定的类指针 int* 2.malloc只负责开辟空间,new不仅仅有malloc的功能,可以进行数据的初始化 new int(20)

  • C++表达式new与delete知识详解

    在C++中,new表达式用于动态创建对象,即在堆(自由存储区)空间上为对象分配内存,而程序员也要小心的使用这些申请来的内存空间,当不再使用时应该调用delete表达式来释放该存储空间并且将指针置零. 本文学习了如何动态创建对象,动态创建的对象与一般对象的区别,动态创建的对象的初始化以及释放动态分配的内存等知识点. C++中分配的内存大致有三类:静态存储区,栈内存和堆内存 其中,静态存储区是在程序编译阶段就已经分配好的,用于全局变量,static变量等:堆栈是比较常用的对象存储方式. new和de

  • C++中new和delete的介绍

    介绍 1.malloc,free和new,delete区别. a.malloc,free是C/C++的标准库函数.new,delete是c++的操作符. b.malloc申请的是内存,严格意义不是"对象",new申请的可以理解为"对象",new 时会调用构造函数,返回指向该对象的指针. c.对于class类型,必须用new/delete来创建和销毁,自动调用构造和析构函数,malloc/free无法胜任. 2.使用new遵循原则: a.用new申请的内存,必须用de

  • C++的new和delete详解

    目录 1.new和delete的内部实现 2.placement技术 3.new和delete运算符重载 4.对象的自动删除技术 1.new和delete的内部实现 C++中如果要在堆内存中创建和销毁对象需要借助关键字new和delete来完成.比如下面的代码 class CA { public: CA()m_a(0){} CA(int a):m_a(a){} virtual void foo(){ cout<<m_a<<endl;} int m_a; }; void main()

  • C++ 使用new与delete需注意的原则

    C++的动态内存管理是通过new和delete两个操作来完成的,即用new来申请空间,用delete来释放空间.在使用new和delete时,注意以下原则. 1.new与delete需一一对应 用new操作申请空间,如果申请成功,必须在以后的某个时刻用delete释放该空间,既不能忘记释放,也不能多次释放.前者会引起内存泄露,后者会引起运行时错误.如下面的程序. #include <iostream> using namespace std; int main() { int *p; p=ne

  • 深入浅析C++的new和delete

    new和delete的内部实现 C++中如果要在堆内存中创建和销毁对象需要借助关键字new和delete来完成.比如下面的代码 class CA { public: CA()m_a(0){} CA(int a):m_a(a){} virtual void foo(){ cout<<m_a<<endl;} int m_a; }; void main() { CA *p1 = new CA; CA *p2 = new CA(10); CA *p3 = new CA[20]; delet

  • C++深入讲解new与deleted关键字的使用

    目录 可执行程序的虚拟地址空间 1.new的运算符用法(关键字) 2.new的函数用法 3.定位new 4.new创建对象 5.delete 6.对于内置类型new/delete/malloc/free可以混用 7.使用注意事项 可执行程序的虚拟地址空间 内核:存放操作系统 栈区:函数的形参,非静态的局部变量,函数现场 保护数据等等,栈是向下增长的. 共享库的内存映射区域:用于装载一个共享的动态内存库.用户可使用系统接口创建共享内存,做进程间通信. 堆区:用于程序运行时动态内存分配,堆是可以上增

  • 最新C/C++中的new和delete的实现过程小结

    目录 new delete new[] delete[] 下面是<C++ Primer 5th>中P726 对 new 和 delete 过程的解释: 当我们使用一条new表达式时,实际上执行了三步操作: new表达式调用一个名为 operator new (或者 operator new[] )的标准库函数.该函数分配一块足够大的.原始的.未命名的内存空间以便存储特定类型的对象(或者对象数组). 编译器运行相应的构造函数以构造这些对象,并为其传入初始值. 对象被分配了空间并构造完成,返回一个

  • 一篇文章了解c++中的new和delete

    目录 new expression delete expression new[]和new() new[]和delete[] new的内存分布 placement new new失败处理 捕捉异常 禁用new的异常 new-handler 重载 重载全局的::operator new 重载局部的Foo::operator new 重载placement new 总结 new expression new一个类型,会创建一个该类型的内存,然后调用构造函数,最后返回该内存的指针 注意:该操作是原子性

  • Angular中封装fancyBox(图片预览)遇到问题小结

    首先在官网下载最新版的fancyBox(一定要去最新网站,以前依赖的jquery版本偏低),附上链接: http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery,然后在引用jquery.fancybox.min.css和jquery.fancybox.min.js. 如果需要动画和鼠标滚轮滚动效果还可以引入他提供的相关工具文件. 1.你可以通过链接.css和.js在你的html文件来安装fancyBox .确保您也加载了jQuery库.以下是用作示例的基本H

  • SpringBoot 中实现跨域的5种方式小结

    一.为什么会出现跨域问题 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现. 同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互.所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port) 二.什么是跨域 当一个请求url的协议

  • SpringBoot中Mybatis + Druid 数据访问的详细过程

    目录 1.简介 2.JDBC 3.CRUD操作 4.自定义数据源 DruidDataSource 1.配置 Druid 数据源监控 2.配置 Druid web 监控 filter 5.SpringBoot 整合mybatis 1. 导入mybatis所需要的依赖 2.配置数据库连接信息 3,创建实体类 4.配置Mapper接口类 6.SpringBoot 整合 1.简介 ​ 对于数据访问层,无论是SQL(关系型数据库) 还是NOSQL(非关系型数据库),SpringBoot 底层都是采用 Sp

  • linux中了minerd之后的完全清理过程(详解)

    一不小心装了一个Redis服务,开了一个全网的默认端口,一开始以为这台服务器没有公网ip,结果发现之后悔之莫及啊 某天发现cpu load高的出奇,发现一个minerd进程 占了大量cpu,google了一下,发现自己中招了 下面就是清理过程 第一步 1.立即停止redis服务,修改端口权限,增加密码措施 2.按照网上的资料 删除 crontab 里的两个内容 sudo rm /var/spool/cron/root sudo rm /var/spool/cron/crontabs/root 3

  • 基于python中pygame模块的Linux下安装过程(详解)

    一.使用pip安装Python包 大多数较新的Python版本都自带pip,因此首先可检查系统是否已经安装了pip.在Python3中,pip有时被称为pip3. 1.在Linux和OS X系统中检查是否安装了pip 打开一个终端窗口,并执行如下命令: Python2.7中: zhuzhu@zhuzhu-K53SJ:~$ pip --version pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7) Python3.X中: z

  • Python3中的列表,元组,字典,字符串相关知识小结

    一.知识概要 1. 列表,元组,字典,字符串的创建方式 2. 列表,元组,字典,字符串的方法调用 3. 列表,元组,字典,字符串的常规用法 二.列表 # 列 表 # 列表基础 list_1 = ['a','b','c','d','e','f'] list_2 = ['apple','banana','watermelon','strawberry','banana','apple'] print(list_1) print("##########") # 列表得下标是从0开始的,之后的

  • Ajax中的JSON格式与php传输过程全面解析

    在Ajax中的JSON格式与php传输过程中有哪些要注意的小地方呢? 先来看一下简单通用的JSON与php传输数据的代码 HTML文件: <input type="button" value="Ajax" id="btn"> <script> var btn = document.getElementById("btn"); btn.onclick = function(){ var xhr = get

随机推荐