• 自在存储区和堆
  • placement-new、new operator、operator new

    • 区别
    • demo1:operator new/operator delete应用
  • new 与 malloc

自在存储区和堆

  • 参考:https://stackoverflow.com/que...
  • 参考:https://www.quora.com/What-is...
  • 参考:https://www.cnblogs.com/qg-wh...
  • 参考:https://blog.csdn.net/nie1994...
  • 两种动态内存区域。

    • heap
    • free store

      C++的内存布局
  • 堆(malloc/free)、栈、自在存储区(new delete)、全局/动态存储区、常量存储区
free store 和 heap的区别(语言背景角度)
  • malloc在堆上调配的内存块,应用 free 开释内存,而 new 所申请的内存则是在自在存储区上,应用 delete 来开释

    • 精确来说free store 对应的是 operator new
  • free store 和 headp是不同内存区域吗(操作系统角度)
多角度探讨异同
  • (编译器上)大部分C++编译器默认应用堆来实现自在存储。也就是说这个时候说它是在堆上还是在自在存储区上都对。
  • (语言背景)堆是C或操作系统概念。自在存储区是C++形象进去的逻辑概念。

    • C++提出该概念更加强调了这两种内存自在调配不应该被互操作,且C++使得内存自在调配更加灵便(placement-new)。
    • C++中应用 malloc 和 free 在技术上是可能的(偶然有用),但这种做法应该防止或至多是孤立的
  • (程序角度)

    • free store:对象的生命周期 能够小于 调配存储空间的工夫(即free store能够在不立刻初始化的状况下分配内存,并且能够再不立刻开释内存的状况下销毁对象)
    • heap:尽管默认的全局 new 和 delete (注:特指::operator new)可能由特定编译器依据 malloc 和 free 实现,但堆与闲暇存储不同,并且在一个区域(heap or free store)中调配的内存不能在另一个区域中平安地开释。

      • 从堆(malloc进去的)中的内存能够用placement-new结构和显式析构,这样的话对于free store对象生存期的阐明再这里也实用。

placement-new、new operator、operator new

  • 参考:https://blog.51cto.com/yiluoh...
  • *参考:https://www.cnblogs.com/luxia...

区别

  • new operator/delete operator就是newdelete操作符,而operator new/operator delete函数。(注:不是很精确,然而很帮忙了解)
  • new operator(操作符)

    • 作用:调配足够的空间(调用 operator new),并且调用对象的构造函数
    • 执行过程:

      • 调用operator new分配内存
      • 调用构造函数生成类对象
      • 返回相应指针
    • 重载:不能够被重载
    • new operator与delete operator的行为是不可能也不应该被扭转,这是C++规范作出的承诺
  • operator new(函数)

    • 作用:分配内存,但不执行结构
    • 重载:能够重载。

      • 返回类型必须申明为void*
      • 第一个参数类型必须为表白要求调配空间的大小(字节),类型为size_t
      • 能够带其它参数
    • 特例:placement new就是`operator new的重载。不分配内存,而是利用已有内存
    • 全局:::operator new,通用操作,在heap中调配
    • operator new与operator delete和C语言中的malloc与free对应,只负责调配及开释空间,然而不可能穿插应用,因为一个对象是free store另一个是heap。
  • placement-new

    • 作用:容许用户把一个对象放到一个特定的中央,达到调用构造函数的成果
    • 重载:placement new 是重载 operator new 的一个规范、全局的版本,它不可能被自定义的版本代替.(不像一般版本的operator newoperator delete可能被替换)

      • 也就是不能重载笼罩
    • 签名:void *operator new( size_t, void * p ) throw() { return p; }
    • placement-new 执行时,疏忽了size_t,该参数没有作用。只应用和返回void* p
    • 应用场景:

      • buffer性能进步:间接new一个数组当缓冲区,会调用构造函数,影响性能。能够先预调配一块内存,之后用placement-new结构
      • 节俭了堆中找足够大的空间 的工夫。placement-new的内存调配是常数工夫,因为曾经调配好了。
    • 辨别一般new:

      • Widget * p = new Widget; //ordinary new
      • pi = new (ptr) int; pi = new (ptr) int; //placement new
为什么有必要写本人的operator new和operator delete?
  • 效率。具体看《Effective C++》中的第二章内存治理
Placement new应用步骤
  • 步骤1:调配缓存空间,有三种形式

    1. 堆中获取

      • char * buff = new [N*sizeof(Task)]; //分配内存
    2. 栈上获取

      • char buf[N*sizeof(Task)]; //分配内存
    3. 间接用地址。(地址必须有有意义)

      • void* buf = reinterpret_cast<void*> (0xF00F);
  • 步骤2:对象的结构

    • Task *ptask = new (buf) Task
  • 步骤3:应用

    • ptask->memberfunction();
  • 步骤4:对象的析构

    • ptask->~Task();
    • 必须显示调用析构
  • 步骤5:开释缓存空间

    • 能够重复利用缓存并给它调配一个新的对象(反复步骤2,3,4)
    • delete [] buf;

  • 如果你的确须要应用placement new,请认真遵循以上的步骤。

demo1:operator new/operator delete应用

#include <iostream>#include <string>using namespace std;class X{public:    X() { cout<<"constructor of X"<<endl; }    ~X() { cout<<"destructor of X"<<endl;}    void* operator new(size_t size,string str)    {        cout<<"operator new size "<<size<<" with string "<<str<<endl;        return ::operator new(size);    }    void operator delete(void* pointee)    {        cout<<"operator delete"<<endl;        ::operator delete(pointee);    }private:    int num;    // 4字节};int main(){    // 调用 new 操作符(留神不是operator new),这里须要传入 行将调用operator new所需的第二个参数,size参数 new操作符会本人给    X *px = new("A new class") X;    delete px;    return 0;}
operator new size 4 with string A new classconstructor of Xdestructor of Xoperator delete
  • 后果解析

    • X *px = new("A new class") X;中,调用的是 new 操作符(留神不是operator new),这里须要传入 行将调用operator new所需的第二个参数,size参数 new操作符会本人给
    • delete px;(为delete operator)时,先调用析构函数,再调用operator delete

new 与 malloc

  • https://www.cnblogs.com/qg-wh...
特色new/deletemalloc/free
分配内存的地位自在存储区
内存调配胜利的返回值残缺类型指针void*
内存调配失败的返回值默认抛出异样返回NULL
分配内存的大小由编译器依据类型计算得出必须显式指定字节数
解决数组有解决数组的new版本new[]须要用户计算数组的大小后进行内存调配
已分配内存的裁减无奈直观地解决应用realloc简略实现
是否互相调用能够,看具体的operator new/delete实现不可调用new
分配内存时内存不足客户可能指定处理函数或重新制定分配器无奈通过用户代码进行解决
函数重载容许不容许
构造函数与析构函数调用不调用