重载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. Hadoop YARN架构设计要点

    YARN是开源项目Hadoop的一个资源管理系统,最初设计是为了解决Hadoop中MapReduce计算框架中的资源管理问题,但是现在它已经是一个更加通用的资源管理系统,可以把MapReduce计算框 ...

  2. 【mac】ansible安装及基础使用

    安装 环境释放 mac 10.12.5 #more /System/Library/CoreServices/SystemVersion.plist 安装命令 #ruby -e "$(cur ...

  3. 为Linux配置常用源:epel和IUS

    CentOS上,除了os类的yum源,还需要配置几个常用的源:epel.ius. 有很多国内很多镜像站点都提供了各类仓库的镜像站点,个人感觉比较全的是阿里云http://mirrors.aliyun. ...

  4. IPv6笔记

    单播地址包含的几种类型:1.AGUA地址:2000::到3FFF:FFFF:FFFF:FFFF:FFFF..... 一个接口可以拥有若干个AGUA地址2.Link-Local 地址:FE80::/10 ...

  5. shell编程基础(七): 处理文件命令sed与awk

    一.sed(以行为单位处理文件) sed意为流编辑器(Stream Editor),在Shell脚本和Makefile中作为过滤器使用非常普遍,也就是把前一个程序的输出引入sed的输入,经过一系列编辑 ...

  6. .net DBHelper

    DBHelper.cs是程序来连接数据的,也是一个程序必不可少的一个类(本人道行浅,目前这样认为).由于一个程序基本写一次,容易忘记.所有写在这里备注 首先是引用 using System.Data; ...

  7. [转]OmniLayer / omnicore API 中文版

    本文转自:https://www.codetd.com/article/1692438 JSON-RPC API Omni Core是Bitcoin Core的一个分支,其Omni协议功能支持作为顶层 ...

  8. 【转】JS正则表达式大全(整理详细且实用)

    正则表达式中的特殊字符 字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个 ...

  9. 一个小时学会Maven

    一.为什么要Maven 在开发中经常需要依赖第三方的包,包与包之间存在依赖关系,版本间还有兼容性问题,有时还里要将旧的包升级或降级,当项目复杂到一定程度时包管理变得非常重要. Maven是当前最受欢迎 ...

  10. 关于Maven项目build时出现No compiler is provided in this environment的处理

    版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/lslk9898/article/details/73836745 近日有同事遇到在编译Maven项目时 ...