zoukankan      html  css  js  c++  java
  • C++中的new与delete总结

    1. operator new、operator delete与new、delete操作符的区别:

    • operator new的作用类似于malloc,负责分配内存;operator delete的作用类似于free,负责释放内存
    • new操作符包括两个步骤;调用适当的operator new版本分配内存;在分配的内存上调用构造函数
    • delete操作符包括两个步骤:在内存上调用析构函数;调用适当的operator delete版本释放内存
    • operator new和operator delete函数可以重载、重写(名字遮掩),而new/delete操作符不可

    2. 标准库提供的operator new/delete(C++11)

    标准库提供的global operator new,在全局名字空间中定义:
    	
        void* operator new (std::size_t size); //抛出异常的版本
        void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept; //不抛出异常的版本,内存不足则返回nullptr
        void* operator new (std::size_t size, void* ptr) noexcept; //placement new,仅仅返回ptr值,未作内存分配
    对应的global operator delete:
        void operator delete (void* ptr) noexcept;
        void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) noexcept;
        void operator delete (void* ptr, void* voidptr2) noexcept;//本函数未做任何事情

    3. operator new与operator delete:层次关系、版本、对应关系与new handler

    • 层次关系:C++标准中仅建议在两种“作用域”中定义operator new/delete,即在类中作为类的static成员或在global作用域中。在使用Class1 *pc = new Class1;的形式创建动态对象时,new操作符首先在当前类(Class1)中查找operator new的相应版本,若未找到,则会到基类中递归查找,若还未找到,则会到global作用域中查找。查找过程中使用“名字遮掩规则”
    • 版本:
      1. 标准版:标准版的operator new只有一个size_t类型的参数;标准版的operator delete只有 void*类型参数;另外,operator delete还有一个特别成员版:有void *类型参数和size_t类型参数(只可在class中定义)。若类中同时定义了这两种operator delete,则优先使用前者。
      2. 非标准版:Effective C++中称之为placement版,并指出其多义性,而C++标准中将placement语义留给了上述提到标准库的第三个函数。非标准版的operator new可以有除了第一个size_t参数以外的其他参数,原型形式为:void* operator new(std::size_t size, type1 arg1, type2 arg2...); 通过new操作符间接调用的形式为: new(arg1, arg2, ...)ClassX; 非标准版的operator delete除了有第一个void*类型的参数还有额外的参数,其原型形式为:void* operator delete(void *ptr, type1 arg1, type2 arg2 ...); 非标准版的operator delete会在相应的operator new调用后对象的构造函数发生异常时由编译器调用。
      3. 注:关于operator delete的“特别成员版”。若类中同时有标准形式的operator delete作为成员,则delete操作符优先使用标准形式的operator delete,即时在异常抛出(下文会解释这是什么异常情况)时也是如此。另外,非标准版的operator new并没有与之参数对应的“特别成员版”
    不同形式的operator new与operator delete:
        void* operator new (std::size_t size); //全局标准版operator new
        void operator delete(void* ptr);//全局标准版operator delete
        class A{
        public:
            static void operator new(size_t size);//类专属标准版operator new
            static void operator delete(void* ptr, size_t size) noexcept;//类特别成员版operator delete
            static void operator delete(void* ptr) noexcept;//类专属operator delete
        };
    • 对应关系:
      1. 标准版:void* operator new(std::size_t size)可与两种operator delete对应,即void operator delete(void* ptr)或void operator delete(void*ptr, size_t)。且无论在正常情况下,还是异常情况下,C++优先使用第一种operator delete
      2. 非标准版:void* operator new(std::size_t size, ...)与void operator delete(void* ptr, ...)对应。未发生异常时,C++编译器调用operator new(标准版或非标准版依据new操作符是否传递额外参数而定)分配内存,调用标准版的operator delete(无论该内存是否通过标准版的operator new)释放内存。异常发生时(operator new成功调用,但调用对象构造函数时发生异常),编译器会调用与operator new参数对应的operator delete版本,若未找到,则不会调用其他形式的operator delete
    • operator new与new handler。编写自定义的operator new,在发生异常或内存不足时,应正确调用已设置的new handler

    4. 自定义operator new与operator delete

    • 可以重新定义标准库提供的非placement版本的operator new和operator delete
    • 建议在global和class作用域中重写或重载自定义的operator new和operator delete

    5. operator new/delete与类层次

    • 类的operator new成员通常仅负责当前类的内存分配,并不负责子类的内存非配
    • 类的析构函数应该是virtual的,否则Base *pb = new Derived; delete pb;将不能传递正确的size_t参数给子类的operator delete成员

    6. operator new/delete与operator new[]/delete[]

    • 以上规则均适用于operator new[], operator delete[],仅仅是函数名字不同
    参考:
  • 相关阅读:
    vue 手动挂载 $amount()
    Redis 主从配置
    DMA分区管理
    C# 构造函数里的base和this的区别
    SQL Server 数据库性能优化
    TCP和UDP的优缺点及区别
    Django框架初步应用简述
    前端vue框架应用雏形
    接口mock之moco
    python进阶(九)~~~协程、进程池、线程/进程/协程对比
  • 原文地址:https://www.cnblogs.com/pangblog/p/3367749.html
Copyright © 2011-2022 走看看