new operator /operator new 和placement new

本文介绍这三种new/delete之间的区别和联系。

new operator

new operator(new运算符)是我们C++中常用的运算符,比如A* a = new A;创建一个A对象指针。

new operator分为两步:

1.基于类型的size调用operator new分配一块内存。如果A中重载了operator new,就调用A::operator new(size_t),否则调用全局默认C++自己提供的::operator new(size_t)

2.构造对象。

operator new

C++默认提供一个operator new函数,它是一种通用的内存分配器,可以分配任意大小的内存块。

比如T * tmp = (T*)(::operator new(size_t)size);创建一个大小为size的内存块,指针tmp指向这块内存块。

operator delete也要可以释放任意大小的内存块。operator delete想弄清它要释放的内存有多大,就必须知道当初operator new分配的内存有多大。有一种常用的方法可以让operator new来告诉operator delete当初分配的内存大小是多少,就是在它所返回的内存里预先附带一些额外信息,用来指明被分配的内存块的大小。也就是说,当你写了下面的语句,

airplane *pa = new airplane;

你不会得到一块看起来象这样的内存块:

pa——> airplane对象的内存

而是得到象这样的内存块:

pa——> 内存块大小数据 + airplane对象的内存

重写operaotr new

operator new的工作是分配内存,为什么要重写:为了效率。有些类占用内存非常小,每次创建都分配内存太慢,可以先分配一块大的内存池,然后每次在内存池里面直接构造对象。

比如有一个飞机类:

    class airplanerep { ... };      // 表示一个飞机对象
    class airplane {
    public:
      ...
    private:
      airplanerep *rep;             // 指向实际描述
    };

一个airplane对象并不大,它只包含一个指针,当调用operator new来分配一个airplane对象时,得到的内存可能要比存储这个指针(或一对指针)所需要的要多。为什么,我们之前介绍了,C++提供的默认operator new分配的内存需要记录内存的size。

通过重写operator new,可以设计特有的分配内存方式。比如http://www.kuqin.com/effectivec2e/ch02e.htm中创建airplane时首先创建一大块内存,并且使用链表的方式控制未使用的内存区域。每次new的时候,从链表中选择一个节点作为分配的内存。

重写了operator new以后,当使用new operator构建一个对象的时候,会自动去调用operator new函数,将返回的指针作为分配好的指针。

在自己重写operator new分配的大内存上创建的对象,不能使用delete直接把内存删除。

问题出在operator new(在airplane里定义的那个)返回了一个不带头信息的内存的指针,而operator delete(缺省的那个)却假设传给它的内存包含头信息。这就是悲剧产生的原因。

placement new

placement new是在已经分配好的内存上,构造一个对象。如new(p)T(value),在p指向的已分配好的内存首地址上,使用构造函数T(value)构造一个新的T对象。

讨论

new operator没有什么好说的,就是我们平时使用的new操作符,他会请求分配一块内存然后构造对象。

当我们需要自己控制内存申请机制的时候,比如我们希望创建一个内存池,然后在这块内存上构造对象,有两种方法:

1.重写operator new

http://www.kuqin.com/effectivec2e/ch02e.htm中举的例子。为类重写了operator new以后,类构造对象的时候,自动去调用重写的operator new分配内存。

2.使用placement new

首先申请一块内存(可以使用默认的operator new),然后在这块内存上创建对象。

T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));//申请内存

new (p)T1(value)//构造函数
时间: 2024-08-01 18:27:54

new operator /operator new 和placement new的相关文章

C++ new operator, delete operator, operator new, operator delete, new placement

http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html http://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/ new operator 就是C++中定义的关键字new,调用new而触发的行为,del

【转】C++易混知识点3. New Operator, Operator New, Placement New 实例分析,比较区别

我们知道,C++中引入了New 这个内置符号,很大方便了指针的使用,程序员不必关注与这块堆上新分配的内存是如何来的,如何初始化的,然后如何转换为我们想要的类型指针的.现在,我们重点来分析下这个NEW内置符号背后的步骤和所调用到的函数.这里面涉及到new operator, operator new, placement new. 转载请注明出处: http://blog.csdn.net/elfprincexu 1. New Operator (__type__ * a = new a();)

C++内存管理(new operator/operator new/operator delete/placement new)

new operator 我们平时使用的new是new操作符(new operator),就像sizeof一样是语言内置的,不能改变它的含义,功能也是一样的 比如: string *ps = new string("Memory Management"); 相当于 void *memory = operator new(sizeof(string)); // 得到未经处理的内存,为String对象 call string::string("Memory Management&

【转】C++ 内存分配(new,operator new)详解

本文主要讲述C++ new运算符和operator new, placement new之间的种种关联,new的底层实现,以及operator new的重载和一些在内存池,STL中的应用. 一 new运算符和operator new(): new:指我们在C++里通常用到的运算符,比如A* a = new A;  对于new来说,有new和::new之分,前者位于std operator new():指对new的重载形式,它是一个函数,并不是运算符.对于operator new来说,分为全局重载

C++ Primer 学习笔记_29_操作符重载与转换(4)--转换构造函数和类型转换运算符归纳、operator new 和 operator delete 实现一个简单内存泄漏跟踪器

C++ Primer 学习笔记_29_操作符重载与转换(4)--转换构造函数和类型转换运算符归纳.operator new 和 operator delete 实现一个简单内存泄漏跟踪器 一.转换构造函数 可以用单个实参来调用的构造函数定义从形参类型到该类型的一个隐式转换.如下: class Integral { public: Integral (int = 0); //转换构造函数 private: int real; }; Integral A = 1; //调用转换构造函数将1转换为In

Swift在for循环中报错'++' is not a binary operator

最近刚开始学swift,遇到了一个非常诡异的问题.是在写for循环的时候出现语法错误.代码如下: for var i = 0; i < 10; i++{ println("hello world") } 按理说这是Swift里最简单的for循环的使用了.但是编译器还是报了两个错: '++ is not a binary operator' Operator is not a known binary operator 虽然苹果在官方文档里面说,建议通过++i这种方式使用自增运算符

Springside动态组合条件搜索:No enum constant org.springside.modules.persistence.SearchFilter.Operator.GE

如下报错: 16:22:05.566 [http-nio-80-exec-12] ERROR 500.jsp - No enum constant org.springside.modules.persistence.SearchFilter.Operator.GE java.lang.IllegalArgumentException: No enum constant org.springside.modules.persistence.SearchFilter.Operator.GE at

C# 参考之转换关键字:operator、explicit与implicit

operator operator 关键字用于在类或结构声明中声明运算符.运算符声明可以采用下列四种形式之一: public static result-type operator unary-operator ( op-type operand ) public static result-type operator binary-operator ( op-type operand, op-type2 operand2 ) public static implicit operator co

操作符重载operator

发现一篇好文: 转载: 本文主要整理自C++之运算符重载及C++运算符重载总结. 什么是运算符重载 运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生.如:   在这个程序里"+"既完成两个整形数的加法运算,又完成了双精度型的加法运算.为什么同一个运算符"+"可以用于完成不同类型的数据的加法运算?这是因为C++针对预定义基本数据类型已经对"+"运算符做了适当的重载.在编译程序编译不同类型数据的加法表达式时