重载new,delete运算符

new,delete在c++中也被归为运算符,所以可以重载它们。

new的行为:

  • 先开辟内存空间

  • 再调用类的构造函数

开辟内存空间的部分,可以被重载。

delete的行为:

  • 先调用类的析构函数

  • 再释放内存空间

释放内存空间的部分,可以被重载。

为什么要要重载它们?

有时需要实现内存池的时候需要重载它们。频繁的new和delete对象,会造成内存碎片,内存不足等问题,影响程序的正常执行,所以一次开辟一个适当大的空间,每次需要对象的时候,不再需要去开辟内存空间,只需要调用构造函数(使用placement new)即可。

new,delete的重载函数,可以是全局函数,也可以是类内部的公有重载函数;当既有全局的重载函数,也有类内部的公有重载函数时,实际调用的是类内部的公有重载函数。

new,delete可以有多种重载方式,但是,new函数的第一个参数一定要是size_t类型

重载方式1,new单个对象

void* operator new(size_t sz){
void* o = malloc(sz);
return o;
}
void operator delete(void *o){
free(o);
}

重载方式2,new对象的数组

void* operator new[](size_t sz){
void* o = malloc(sz);
return o;
}
void operator delete[](void *o){
free(o);
}

重载方式3,不开辟空间,只是调用给定对象(用地址识别)的构造方法,也叫placement new

//第一个参数size_t即使不使用,也必须有
void* operator new(size_t sz, String* s, int pos){
return s + pos;
}

小例子:

#include <iostream>
#include <string.h>
using namespace std; class String{
public:
String(const char* str = ""){
cout << "Create" << endl;
if(NULL == str){
data = new char[1];
data[0] = '\0';
}
else{
data = new char[strlen(str) + 1];
strcpy(data, str);
}
}
~String(){
cout << "Free" << endl;
delete []data;
data = NULL;
}
private:
char* data = NULL;
};
//重载方式1
void* operator new(size_t sz){
cout << "in operator new" << endl;
void* o = malloc(sz);
return o;
}
void operator delete(void *o){
cout << "in operator delete" << endl;
free(o);
}
//重载方式2
void* operator new[](size_t sz){
cout << "in operator new[]" << endl;
void* o = malloc(sz);
return o;
}
void operator delete[](void *o){
cout << "in operator delete[]" << endl;
free(o);
} //重载方式3
//第一个参数size_t即使不适用,也必须有
void* operator new(size_t sz, String* s, int pos){
return s + pos;
}
int main(){
String *s = new String("abc");
delete s; String *sr = new String[3];
delete []sr; //开辟内存池,但是还没有调用过池里对象的构造方法
String *ar = (String*)operator new(sizeof(String) * 2);
//调用池里第一个对象的构造方法,不再开辟空间
new(ar, 0)String("first0");
//调用池里第二个对象的构造方法 ,不再开辟空间
new(ar, 1)String("first1");
//调用池里第一个对象的析构方法,注意不会释放到内存
(&ar[0])->~String();
//调用池里第二个对象的析构方法,注意不会释放到内存
(&ar[1])->~String();
//下面语句执行前,内存池里的对象可以反复利用
operator delete(ar); }

c/c++ 重载new,delete运算符 placement new的更多相关文章

  1. C++重载new和delete运算符

    内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...

  2. C++学习32 重载new和delete运算符

    内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...

  3. 重载new和delete运算符

    内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内 ...

  4. C++ new operator, delete operator, operator new, operator delete, new placement

    http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/arch ...

  5. C++重载流插入运算符和流提取运算符【转】

    C++的流插入运算符“<<”和流提取运算符“>>”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream.cin和cout分别是 ...

  6. C++运算符重载——输入/输出运算符

    为了与IO标准库一致,重载输入输出运算符函数的第一个行参应该是流的引用,第二个行参是对象的引用. 如果重载为类的成员函数,第一个行参应该是对象的引用,第二个行参是流的引用. 使用方式是 ClassOb ...

  7. operator 重载内置运算符

    operator 关键字来重载内置运算符,或提供类或结构声明中的用户定义转换.它可以定义不同类型之间采用何种转化方式和转化的结果. operator用于定义类型转化时可采用2种方式,隐式转换(impl ...

  8. C++中不可重载5个运算符

    C++中不可重载的5个运算符 C++中的大部分运算符都是可以重载的,只有以下5个运算符不可以重载,他们是: 1  .(点运算符)通常用于去对象的成员,但是->(箭头运算符),是可以重载的   2 ...

  9. 用new和delete运算符进行动态分配和撤销存储空间

    測试描写叙述:暂时开辟一个存储空间以存放一个结构体数据 #include <iostream> #include <string> using namespace std; s ...

随机推荐

  1. web开发的跨域问题详解

    本文由云+社区发表 做过 web 开发的同学,应该都遇到过跨域的问题,当我们从一个域名向另一个域名发送 Ajax 请求的时候,打开浏览器控制台就会看到跨域错误,今天我们就来聊聊跨域的问题. 1. 浏览 ...

  2. MongoDB副本集(一主两从)读写分离、故障转移功能环境部署记录

    Mongodb是一种非关系数据库(NoSQL),非关系型数据库的产生就是为了解决大数据量.高扩展性.高性能.灵活数据模型.高可用性.MongoDB官方已经不建议使用主从模式了,替代方案是采用副本集的模 ...

  3. 一个注意事项:内部类引用的外部变量必须是final的

    之前写过一个项目,好久没更新了,最近翻起以前的代码,发现在这里报了一个错.(现在转到Intellij了,从前在Eclipse luna中是可以编译通过的,Eclipse mars也会报错,JDK版本都 ...

  4. 设计shell脚本选项:getopt

    man 1 getopt翻译:https://www.cnblogs.com/f-ck-need-u/p/9757959.html 写shell脚本的时候,通过while.case.shift来设计脚 ...

  5. JavaScript 系列博客(四)

    JavaScript 系列博客之(四) 前言 本篇介绍 JavaScript 中的对象.在第一篇博客中已经说到 JavaScript 是一种''对象模型''语言.所以可以这样说,对象是 JavaScr ...

  6. IDEA与Eclipse

    IDEA 1 快捷键 快速查找某个类 double shift 显示类结构图 ctrl+H 代码上移或下移 ctrl+shift+up/down 查找文件 ctrl+shift+N 删除当前行 ctr ...

  7. Spark学习(一)

    一.启动Spark 1.standalone模式 方法一: (1)启动主节点 ./sbin/start-master.sh 访问http://127.0.0.1:8080,得到如下页面 注意标记到的链 ...

  8. [转]php模拟post提交请求,调用接口

    本文转自:https://www.cnblogs.com/jiqing9006/p/3949190.html /** * 模拟post进行url请求 * @param string $url * @p ...

  9. 解码 id_token

    简介 id_token是一个特殊的token,在Microsoft Graph的认证和授权过程中颁发,它包含了已认证用户的一些信息.本文将介绍如何通过实例理解id_token,并且演示了如何解码. 准 ...

  10. C#基础知识总结(三)

    摘要 关系表达式.逻辑表达式.分支结构的总结:if-else.if-else if-else.switch-case一.关系运算符 >,==,<… 关系表达式的结果是bool类型,true ...