欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > Effective C++读书笔记——item51(编写new和delete要遵循惯例)

Effective C++读书笔记——item51(编写new和delete要遵循惯例)

2025/10/5 7:39:18 来源:https://blog.csdn.net/weixin_46032775/article/details/145679774  浏览:    关键词:Effective C++读书笔记——item51(编写new和delete要遵循惯例)

当编写自定义的 operator new 和 operator delete 时,需要遵循一些特定的惯例,以确保代码的正确性和兼容性。下面结合代码详细介绍这些惯例。

1. 自定义 operator new 的惯例
  • 返回值规则:若能提供请求的内存,返回指向该内存的指针;若无法分配内存,应遵循规则抛出 std::bad_alloc 异常。
  • 多次尝试分配内存operator new 实际上会多次尝试分配内存,每次失败后调用 new-handling function,只有当 new-handling function 指针为空时才抛出异常。
  • 处理零字节请求:C++ 要求即使请求零字节,operator new 也要返回合理的指针,通常将零字节请求当作一个字节请求处理。
#include <iostream>
#include <new>void* operator new(std::size_t size) throw(std::bad_alloc) {using namespace std;if (size == 0) {size = 1;  // 处理零字节请求}while (true) {void* p = std::malloc(size);  // 尝试分配内存if (p) {return p;  // 分配成功,返回指针}// 分配失败,获取当前的 new-handling functionnew_handler globalHandler = std::set_new_handler(0);std::set_new_handler(globalHandler);if (globalHandler) {(*globalHandler)();  // 调用 new-handling function} else {throw std::bad_alloc();  // 没有 new-handling function,抛出异常}}
}
  • 处理派生类内存分配operator new 成员函数会被派生类继承,若基类的 operator new 是为特定大小的对象调优的,当处理派生类对象分配请求时,若请求大小不符,应将请求转发给标准的 operator new
#include <iostream>
#include <new>class Base {
public:static void* operator new(std::size_t size) throw(std::bad_alloc) {if (size != sizeof(Base)) {return ::operator new(size);  // 大小不符,转发给标准 operator new}// 处理符合大小的请求return std::malloc(size);}
};class Derived : public Base {};int main() {Derived* p = new Derived;  // 调用 Base::operator newdelete p;return 0;
}
  • operator new[] 的注意事项:若要控制数组的内存分配,需实现 operator new[],但它只是分配裸内存,无法对数组中的对象做任何操作,也无法确定数组中对象的数量。
2. 自定义 operator delete 的惯例
  • 处理空指针:C++ 保证删除空指针总是安全的,因此 operator delete 收到空指针时应什么都不做。
  • 处理不同大小的删除请求:类专用的 operator delete 应检查被删除对象的大小,若大小不符,将请求转发给标准的 operator delete
#include <iostream>
#include <new>class Base {
public:static void* operator new(std::size_t size) throw(std::bad_alloc) {if (size != sizeof(Base)) {return ::operator new(size);}return std::malloc(size);}static void operator delete(void* rawMemory, std::size_t size) throw() {if (rawMemory == 0) {return;  // 处理空指针}if (size != sizeof(Base)) {::operator delete(rawMemory);  // 大小不符,转发给标准 operator deletereturn;}std::free(rawMemory);  // 释放内存}
};class Derived : public Base {};int main() {Derived* p = new Derived;delete p;return 0;
}
  • 基类虚析构函数的重要性:若被删除的对象是从缺少虚析构函数的基类派生出来的,C++ 传递给 operator delete 的 size_t 值可能不正确,因此基类应拥有虚析构函数。

总结要点

  • operator new 要点:包含无限循环尝试分配内存,失败时调用 new-handler,处理零字节请求,类专用版本处理大小不符的请求。
  • operator delete 要点:收到空指针时不做处理,类专用版本处理大小不符的删除请求,基类要有虚析构函数。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词