栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

EffectiveC++-条款51:编写 new 和 delete 时需固守常规

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

EffectiveC++-条款51:编写 new 和 delete 时需固守常规

一. 内容
  1. 条款50已经解释了什么时候你需要写个自定义的 new 和 delete,但没有解释你编写时应该遵守什么样的规则,接下来我们将介绍其中的规则。

  2. 对于 operator new:

    • operator new 的返回值很简单。如果它有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没那个能力,就遵循条款49描述的规则。

    • C++ 规定,即使客户要求 0 bytes,operator new也得返回一个合法指针。常用的做法是将 0 bytes 申请量视为 1 bytes 申请量。

    • operator new 内含一个无限循环,除非内存被成功分配或调用 new_handlers 时它们做了条款49描述的哪些事情:让更多内存可用,安装另一个 new_handler,卸除 new_handler,抛出 bad_alloc 异常,调用 abort() 或 exit()…否则 operator new 内的无限循环永远不会结束。

    • 记住没有直接的方式取得 new-handler 函数指针,必须调用 set_new_handler 使用它的返回值。

    • 许多人未意识到 operator new 成员函数会被 derived class 继承,而 operator new 是针对 base class 专门设计的内存分配函数,如果derived class 忘记重写该函数,会导致内存分配出错。简单的做法是令其调用标准版 operator new。

    • 如果打算控制数组内存分配,就得实现 operator new[ ] 。唯一要做的一件事是分配一块原始内存(raw memory)。因为你无法对 array 内不存在的元素做任何事情。对于 base-derived 体系而言,通常来说 derived class 要比其 base class 大,使用 btyes/ sizeof(base) 计算不出 array 元素的实际个数。

      此外,正如条款16所说,动态分配的 arrays 可能需要包含额外的空间用于存放元素的个数。


    示例代码:

    void* operator new(std::size_t Size) throw(std::bad_alloc) {
           if (Size != sizeof(Base)) {
               return ::operator new(Size);
           }
            while(true) {
                //...分配内存
                if ("分配成功") {
                    //...返回首指针
                }else {
                    //...条款49讲述的事情
                }
            }
        }
    
  3. 对于 operator delete:

    • C++ 保证删除 nullptr 指针永远安全。所以我们必须实现这样的保证。

    • 对于 base-derived 体系,不要忘记重写 derived class 的 delete 函数或者调用标准版 operator delete。

      注意,如果删除的对象派生自某个 base class 而后者缺少 virtual 析构函数,那么 C++ 传给 operator delete 的 size_t 数值可能不正确,导致析构行为异常,这也是条款7所强调的内容。


    示例代码:

    void operator delete(void* RawMemory, std::size_t Size) throw() {
            if (RawMemory == nullptr) {
                return;
            }
            if (Size != sizeof(Base)) {
                return ::operator new(Size);
            }
            //...释放内存
            return;
        }
    
二. 总结
  1. operator new 应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用 new-handler。它也应该有能力处理 0 bytes 申请。 Class 专属版本则还应该处理比正确大小更大的(错误)申请。
  2. operator delete 应该在收到 nullptr 指针时不做任何事。Class 专属版本则还应该处理比正确大小更大的(错误)申请。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026769.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号