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

首先,我们先看一下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. python str find & index 联系

    [1]相同点 (1)功能:检测字符串中是否包含子字符串str (2)语法: [1] str.find(str, beg = 0, end = len(string)) [2] str.index(st ...

  2. MySQL数据排序asc、desc

    数据排序 asc.desc1.单一字段排序order by 字段名称 作用: 通过哪个或哪些字段进行排序 含义: 排序采用 order by 子句,order by 后面跟上排序字段,排序字段可以放多 ...

  3. Spring Boot 的 application.properties

    更改默认端口:8080 server.port = 8081 更改context-path :/server.context-path = /springboot #server.address= # ...

  4. JS的防抖与节流

    JS的防抖与节流在进行窗口的resize.scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕.此时我们可以采用debounce(防抖)和t ...

  5. /* * 有五个学生,每个学生有3门课的成绩,从键盘输入以上数据 *(包括学生号,姓名,三门课成绩),计算出平均成绩, *将原有的数据和计算出的平均分数存放在磁盘文件"stud"中。 */

    1.Student类:类中有五个变量,分别是学号,姓名,三门成绩 package test3; public class Student { private int num; private Stri ...

  6. 【mysql】逗号分割字段的行列转换

    由于很多业务表因为历史原因或者性能原因,都使用了违反第一范式的设计模式,即同一个列中存储了多个属性值.这种模式下,应用常常需要将这个列依据分隔符进行分割,并得到列转行的结果:这里使用substring ...

  7. oracle中number数据类型简单明了解释

    NUMBER (p,s) p和s范围: p 1-38 s -84-127 number(p,s),s大于0,表示有效位最大为p,小数位最多为s,小数点右边s位置开始四舍五入,若s>p,小数点右侧 ...

  8. github笔记

    git config --global user.name"liuhongli1"liuhongli@liuhongli:~/github/test$ git config --g ...

  9. 【常见错误】Quartz常见错误

    1.集群之后把其中一个Quartz服务停了,其他的也不接手工作 问题描述 集群之后,A节点执行了大多数任务,B节点大部分时间处于空闲,停掉A节点,B节点也不会接手工作. 解决方式 修改Quartz的配 ...

  10. java程序员面试交流项目经验

    粘贴自:https://blog.csdn.net/wangyuxuan_java/article/details/8778211 1:请你介绍一下你自己 这是面试官常问的问题.一般人回答这个问题过于 ...