技术在于交流、沟通,本文为博主原创文章转载请注明出处并保持作品的完整性

首先,我们先看一下C++应用程序,使用memory的途径如下图所示

C++应用程序中申请内存基于分配器的实现(std::allocator),而分配器基于C++primitives(new,new[]...),c++primitives基于C语言中的malloc/free..,当然越底层的函数效率越高.

那我们会想,直接用最底层的实现多好,效率还高.但如果你直接调用底层的函数去实现功能,虽然你的效率提高了,但你的程序的可移植性就会相应的降低.

不可否认底层语言的实现,体现出一定的个人能力.但过多的篇幅去实现底层语言,会影响开发效率.


下面说一下C++三种申请内存的工具,然后介绍一下这三种工具的简单使用

A.new operator, delete operator : 申请内存+构造函数

B.new[], delete[] : 用于数组类的操作

C.placement new : 定点new


一 new operator, delete operator,

分配内存的函数的对应关系如下图,下面主要介绍一下下面这些函数的简单使用

int main()
{
void* p1 = malloc(); //512bytes
free(p1); complex<int>* p2 = new complex<int>; //one object
delete p2; void* p3 = ::operator new();// 512bytes
::operator delete(p3); //一下函数都是non-static,一定要通过object调用,分配7个int的内存
void* p4 = allocator<int>().allocate();//allocator<int>()创建临时对象
allocator<int>().deallocate((int*)p4,); return ;
}

我们都知道 new = operator new + 构造函数,delete = 析构函数 + operator delete .如果以代码的形式表现出来应该是这样

比如我们创建一个复数类,

Complex* pc = new Complex(,);

那么编译器会将上面的代码翻译成

    try
{
void* mem = operator new(sizeof(Complex)); //allocate pc = static_cast<Complex*>(mem); //cast pc->Complex::Complex(,); //只有编译器可以直接调用构造函数 }
catch (std::bad_alloc)
{
//申请内存失败...
}

释放内存

delete pc;

编译器翻译为

    pc->~Complex();//先调用析构函数
operator delete(pc);// operator delete的实现基于free()

二 new[]和delete[]

new[],主要运用于数组的申请内存,

如class A 当我们调用

A* p = new A[];//那么就会申请3个class A的内存并调用3次 class A的构造函数

当我们调用 delete[]时

delete[] p; //就会调用3次析构函数 并释放内存(3个class A的内存)

如果我们释放时没有加[]

delete p;

它同样会释放3个class A的内存,但是之后调用其一个构造函数(如果其构造函数内有其他释放内存的操作,那么我们不加[]就会造成内存泄漏)

看一下测试代码

    class A
{
public:
int id; A() : id()
{
cout << "default ctor.this=" << this << " id=" << id << endl;
} A(int i): id()
{
cout << "ctor.this=" << this << " id=" << id << endl;
} ~A()
{
cout << "dtor.this=" << this << " id=" << id << endl;
}
};

测试

    void test_class()
{
A* buf = new A[]; //默认构造函数调用3次 调用顺序 0-1-2
//A必须有默认构造函数 引文new A[3]调用的是默认构造函数 A* tmp = buf;//记录A数组的起点位置 cout << "buf=" << buf << " tmp=" << tmp << endl; for(int i = ; i < ; i++)
{
new(tmp++)A(i); //placement new
} cout << "buf=" << buf << " tmp=" << tmp << endl; delete[] buf;
}

输出结果

我们会发现 delete[] 的顺序与 new[] 的顺序相反,placement后面再说

那么我们这个使用不写[]呢,看看输出结果会怎么样

上面的delete 没有写[], 3个class A的内存是释放了,但是只调用了一次析构函数.


三 placement new

placement new允许我们将object创建与 已经申请好的内存中,但是没有所谓的 placenment delete,因为根本没有分配内存,所以没有placement delete

但是有被称作的placement delete后面说.先看一下placement new

char* buf = new char[sizeof(A) * ];//申请了3个A的内存

A* pc = new(buf)A();//运用申请好的buf的内存,在buf上赋值

上面的new(buf)A();就是placement new.

编译器遇到上面代码会翻译成

A * pc;
try {
void* men = operator new(sizeof(A), buf); //借用内存
pc = static_cast<A*>(mem);//安全转换
pc->A::A();//构造函数
}
catch (std::bad_alloc){
//若失败 不执行构造函数
}

以上就是三种C++申请内存工具的介绍

参考侯捷<<C++内存管理>>

C++内存管理-new,delete,new[],placement new的简单使用的更多相关文章

  1. 内存管理——new delete expression

    C++申请释放内存的方法与详情表 调用情况 1.new expression new表达式在申请内存过程中都发生了什么? 编译器将new这个分解为下面的主要3步代码,①首先调用operator new ...

  2. Java复习2.程序内存管理

    前言: 国庆节的第三天,大家都回家了,一个人在宿舍好无聊.不过这年头与其说是出去玩不如是说出去挤,所以在学校里还是清闲的好.找工作不用担心了,到时候看着你们慢慢忙:插个话题,大学都没有恋爱过,总之各种 ...

  3. C/C++(C++内存管理,内联函数,类型转换,命名空间,string类)

    ---恢复内容开始--- 内存管理 new/delete C语言中提供了 malloc 和 free 两个系统函数,#include "stdlib.h"库函数,完成对堆内存的申请 ...

  4. 【UE4 C++】UObject 创建、销毁、内存管理

    UObject 的创建 NewObject 模板类 本例使用 UE 4.26,只剩下 NewObject 用来创建 UObject,提供两个带不同可选参数构造函数的模板类 Outer 表示这个对象的外 ...

  5. iOS 非ARC基本内存管理系列 -手把手教你ARC——iOS/Mac开发ARC入门和使用(转)

    手把手教你ARC——iOS/Mac开发ARC入门和使用 Revolution of Objective-c 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流 ...

  6. Delphi中ARC内存管理的方向

    随着即将发布的10.3版本,RAD Studio R&D和PM团队正在制作Delphi在内存管理方面的新方向. 几年前,当Embarcadero开始为Windows以外的平台构建新的Delph ...

  7. iOS 内存管理的一点小问题

    现在大家的项目应该基本都是ARC了,如果还是MRC的话,赶紧转换到ARC吧!最近被临时拉过去开发iPad,由于项目原因,还是使用的MRC.今天在调部分界面的时候,发现一段代码,我怎么看都怎么觉得怪怪的 ...

  8. Golang内存管理

    Golang 内存管理 原文链接[http://legendtkl.com/2017/04/02/golang-alloc/] Golang 的内存管理基于 tcmalloc,可以说起点挺高的.但是 ...

  9. BEP 7:CUDA外部内存管理插件(下)

    BEP 7:CUDA外部内存管理插件(下) Numba依赖 向库中添加EMM插件的实现自然会使Numba成为库的依赖项,而以前可能没有.为了使依赖关系可选,如果需要的话,可以有条件地实例化并注册EMM ...

随机推荐

  1. angular和vue还有jquery的区别

    angularjs简单介绍和特点 首先angular是一个mvc框架, 使用mvc解耦, 采用model, controller以及view的方式去组织代码, 会将一个html页面分成若干个模块, 每 ...

  2. Windows cmd 一些命令

    运行是Windows的必要组成部分,可以简单理解为一个应用程序快速调用的组件.通过“运行”窗口,可以调用Windows中任何应用程序甚至DOS命令.一般可以搜索百度百科 微软件(窗口) + R    ...

  3. bzoj2880

    打公式好麻烦 QAQ 为了节省时间去复习,原谅我引用一下别人的博客...http://blog.csdn.net/acdreamers/article/details/8542292 #include ...

  4. oracel数据库主键自增

    -- Create sequence create sequence FILE_ID_SEQ   主键名(自增列) minvalue 1         起始 maxvalue 99999     最 ...

  5. C++ WINDOWS 防多开

    我们有些程序是可以同时运行多个进程,典型的像Visual Studio.但有些就能一次运行一个进程.比如Outlook.那你可能会问啥时可以让它同时打开多个应用程序,啥时只能一个啊.这个主要看进程间是 ...

  6. ElasticSearch(七) Elasticsearch在Centos下搭建可视化服务

    要想可视化ElasticSearch,就需要安装一些插件,安装插件的前提是安装所依赖的环境,比如java,maven等,本篇博文就不再走那些流程了.没安装的童鞋可以看我的ElasticSearch栏目 ...

  7. java限制map大小,并FIFO淘汰

    有时候需要往一个MAP中写入一些记录,但又怕无限制地写入会导致内存爆掉,所以得限制这个MAP的大小. 实现:LinkedHashMap提供了简单的方法. 首先,定义一个最大数,比如1000,然后new ...

  8. Golang实现九九乘法表

    代码相对比较简单,考虑一点细节,就可以了. package main; import ( "fmt" "strconv" ); func Chengfabiao ...

  9. Oracle 12c 的RMAN备份

    备份 rman只备份cdb 只备份CDB数据库需要具有SYSDBA或SYSBACKUP权限用户连接到CDB的root环境下,执行backupdatabase root命令即可完成对CDB的备份,方法如 ...

  10. 在res文件下新建文件夹

    今天遇到了在res下新建文件夹的问题,无论是是Android studio中直接建还是在下载Android studio的物理地址中直接新建一个文件夹,在树结构中始终没有见到新建的文件,原来需要把An ...