重载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. MySQL中字段字符集不同导致索引不能命中

    今天写了一个sql,其中涉及的表中的数据量都差不多为50w左右,查询发现用了8s.这个只是测试服上数据,放到正式服上,肯定一运行就挂了. SELECT Orders. NO, GuidNo, Orde ...

  2. MySQL高可用之组复制(4):详细分析组复制理论

    MySQL组复制系列文章: MySQL组复制大纲 MySQL组复制(1):组复制技术简介 MySQL组复制(2):配置单主模型的组复制 MySQL组复制(3):配置多主模型的组复制 MySQL组复制( ...

  3. Python面向对象基础:设置对象属性

    用类存储数据 类实际上就是一个数据结构,对于python而言,它是一个类似于字典的结构.当根据类创建了对象之后,这个对象就有了一个数据结构,包含一些赋值了的属性.在这一点上,它和其它语言的struct ...

  4. 第一册:lesson sixty five.

    原文: Not a baby. A:What are you going to do this evening Jill? B:I'm going to meet some friends, dad. ...

  5. 【转载】Windows Server2012安装IIS服务器

    在云服务器的使用过程中,很多人由于习惯或者实际需要,会选择Windows Server系统服务器,较常用的版本有Windows Server2008.Windows Server2012.在Windo ...

  6. [日常] HTTP的媒体类型

    HTTP的媒体类型 1.MIME类型的数据格式标签(MultIpurpose Internet Mail Extension) 2.最初用于电子邮件系统之间搬移,多用途互联网邮件扩展 3.MIME类型 ...

  7. 挑战常规--为什么不应该使用Jsonp进行跨域

    常规跨域的方法 常见跨域的方法有: 添加Access-Control-Allow-Origin 后台服务器代理 Jsonp 1.2两种方法都是安全可靠的,3是不安全不可靠的 Json的本质 Json本 ...

  8. 自动化运维经验谈,以及为什么Docker是革命性的

    互联网+的需要 在信息越来越繁杂的互联网时代,公司所运行的项目越来越多,项目相关服务繁多,服务之间存在复杂的依赖关系,运维与管理任务越来越繁重,手工交付需要花费很多的人力与时间,且安全性和时效性均无法 ...

  9. EJS-初识

    项目中使用了EJS,因此,也开始接触了EJS. EJS官方定义:it's just plain JavaScript. 总的来说,上手较快(毕竟我是个菜鸟). 第一步:安装: 第二部使用: 在html ...

  10. Could not open input file: artisan 【Laravel初体验】

    1,情景描述:在命令行窗口写入php artisan make:model Models\MenuModel用于创建模型时,出现此错误(Could not open input file: artis ...