zoukankan      html  css  js  c++  java
  • [C++再学习系列] 深入new/delete:类域的operator new重载

    类域的operator new重载

    class 重载 operator new 时必须定义为类的静态函数 ( 默认为 static 函数 ) 。重载 operator new 更多的是为了提高程序效率,比如使用静态内存代替动态分配,启用小对象分配器等。但是要正确重载类域的 operator new 并不容易,有很多规则需要注意: 1) 总是成对提供 new/delete2) 如重载 operator new 一定要同时提供标准形式的 new举例:

    class T {

       static void* operator new(std::size_t);

        static void* operator new(std::size_t, CustomAllocator&);

     

        static void operator delete(void*, std::size_t);

    };

    T* p = new(alloc) T;

    上述代码将被编译器展成下述代码 ( 猜测,如果有高人知道如何查看编译器生成的中间代码,烦请告知)

    // compiler-generated code for T* p = new(alloc) T;

    //

    void* __compilerTemp = T::operator new (sizeof(T), alloc);  // 1

    T* p;

    try {

      p = new (__compilerTemp) T;      // 2 // construct a T at address __compilerTemp

    }

    catch(...) {                        // constructor failed, attention here…

      T::operator delete (__compilerTemp, sizeof(T), alloc);  // 3

      throw;

    }

           注释 1operator new 用于分配内存, new 的第一步骤;

           注释 2placement new 用于在于地址上构建对象,也就是调用 T 的构造函数。

           注释 3 :与 operator new 配套的 operator delete

     

           C++ 标准规定:当且仅当 operator delete 的重载存在时,以上代码才能生成。否则,在构造函数失败的情况下,代码不会调用 operator delete 。也就是说,如果构造函数抛异常,内存将泄漏。

    这意味着:当提供 void* operator new(parms) 重载时,必须同时提供 void operator delete(void*, parms), 这里参数列表的第一个参数总为 std::size_t 。 对于 operator new[] 也是如此。例外,对于 placement new 由于并不实际分配内存,可不重载相应的 operator delete

     重载opeartor new函数的隐藏

    避免隐藏全局的operator new 和基类重定义的 operator new

           前面已经提到过 C++ 名字查找规则,对于重载的 operator new 也需要遵循此规则。当类中重载 operator new ,那么全局的 operator new 将被隐藏;如果派生类重载 operator new ,那么基类的版本将被隐藏。由于 placement new 大量用于 STL 的优化中,故一定要避免隐藏 placement new 。隐藏 operator new 的这类错误编译器会给出提示。 

           重载 opeartor new 并避免隐藏全局 operator new 的途径:

           1) 对于基类重载的 operator new ,使用 using 来导入相应名字。

    class C : public B {// …

    public:

        static void* operator new(size_t, MemoryPool&); // private version

        using B::operator new;

           };

           2) 对一般重载 operator new 的类,除了提供私有版本外,应该对所有全局 operator new 形式提供转换函数。如下:

    class C {// …

    public:

    static void* operator new(size_t, MemoryPool&);   // private version 

      static void* operator new(std::size_t s) {

      return ::operator new(s);        // global version

      }

      static void* operator new(std::size_t s, std::nothrow_t nt) throw() {

      return ::operator new(s, nt);

      }

      static void* operator new(std::size_t s, void* p) {

      return ::operator new(s, p);

      }

    };

    相关文章:

    深入new/delete:New的3种形态

    深入new/delete:Operator new的全局重载

    派生类函数的重实现规则(override-覆盖)

    ---------------------------------------------------

    兄弟的公司:立即购--手机购物,诚信网购

    兄弟的公司:立即团

    欢迎转载,请注明作者和出处

  • 相关阅读:
    Android Static分析
    hdoj 1285 确定比赛名次 【拓扑排序】
    Sqoop2安装记录
    Activiti源代码分析
    SpringBoard 无法启动应用程序(错误:-3)
    关于public、private、protected、internal
    Java基础——Statement与PrepareStatement
    无password身份验证:安全、简单且部署高速
    说说Linux文件权限那些事儿
    Android中Service概述
  • 原文地址:https://www.cnblogs.com/zhenjing/p/class_new.html
Copyright © 2011-2022 走看看