c/c++ 重载new,delete运算符 placement new

重载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);

}

原文地址:https://www.cnblogs.com/xiaoshiwang/p/9515202.html

时间: 2024-10-03 13:20:14

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

重载类的new和delete运算符成员函数

重载类的new和delete运算符成员函数1. 调用new时,先分配内存,后调用构造函数.调用构造函数的行为由编译器控制.2. 调用delete时,先调用析构函数,后释放内存.调用析构函数的行为由编译器控制.重载这两个运算符函数的目的是为了控制内存的分配与释放.如果需要对某个类型频繁地创建和销毁大量的对象,new和delete运算过程可能会耗费过多的时间,并且会产生过多的内存碎片.这两个运算符函数的原型:void * operator new(size_t sz);void operator d

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

内存管理运算符 new.new[].delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数.一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内存时才会重载. 重载 new 有两种形式: //以类的成员函数的形式进行重载 void * 类名::operator new ( size_t size ){ //TODO: } 和 //以全局函数的形式进行重载 void * operator new ( size_t size ){ //TODO

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/archive/2012/08/10/2631812.html http://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/ new operator 就是C++中定义的关键字new,调用new而触发的行为,del

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载、!运算符重载、赋值运算符重载 、String类([]、 +、 += 运算符重载)、&gt;&gt;和&lt;&lt;运算符重载

C++ Primer 学习笔记_27_操作符重载与转换(2)--++/--运算符重载.!运算符重载.赋值运算符重载 .String类([]. +. += 运算符重载).>>和<<运算符重载 一.++/--运算符重载 1.前置++运算符重载 成员函数的方式重载,原型为: 函数类型 & operator++(); 友元函数的方式重载,原型为: friend 函数类型 & operator++(类类型 &); 2.后置++运算符重载 成员函数的方式重载,原型为:

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

C++中不可重载的5个运算符 C++中的大部分运算符都是可以重载的,只有以下5个运算符不可以重载,他们是: 1  .(点运算符)通常用于去对象的成员,但是->(箭头运算符),是可以重载的 2  ::(域运算符)即类名+域运算符,取成员,不可以重载 3  .*(点星运算符,)不可以重载,成员指针运算符".*,即成员是指针类型 4  ?:(条件运算符)不可以重载 5  sizeof不可以重载

网易云课堂_C++程序设计入门(下)_第8单元:年年岁岁花相似– 运算符重载_第8单元 - 作业2:OJ编程 - 重载数组下标运算符

第8单元 - 作业2:OJ编程 - 重载数组下标运算符 查看帮助 返回 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业截止时间之前不限次数提交答案,系统将取其中的最高分作为最终成绩. 练习数组下标运算符重载 依照学术诚信条款,我保证此作业是本人独立完成的. 1 练习数组下标运算符重载(6分) 本题目具体内容请参见 [第8单元 - 单元作业2说明] 时间限制:500ms内存限制:32000kb #include <iostream> #in

C++对象模型——new 和 delete 运算符(第六章)

6.2    new 和 delete 运算符 运算符 new 的使用,看起来似乎是个单一运算,像这样: int *pi = new int(5); 但事实上它是由以下两个步骤完成: 1.通过适当的 new 运算符函数实体,配置所需的内存: // 调用函数库中的new运算符 int *pi = __new(sizeof(int)); 2.给配置得来的对象设立初值: *pi = 5; 更进一步地,初始化操作应该在内存配置成功(经由 new 运算符)后才执行: // new运算符的两个分离步骤 //

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

测试描述:临时开辟一个存储空间以存放一个结构体数据 #include <iostream> #include <string> using namespace std; struct Student { string name; int age; char sex; }; int main() { Student *p; //定义指向结构体类型Student的数据的指针变量p p=new Student; //用new运算符开辟一个存放Student型数据的空间,把地址赋给p p-

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

为了与IO标准库一致,重载输入输出运算符函数的第一个行参应该是流的引用,第二个行参是对象的引用. 如果重载为类的成员函数,第一个行参应该是对象的引用,第二个行参是流的引用. 使用方式是 ClassObj << cout 这样与标准IO库就不一致了,所以输入输出运算符不能重载为类的成员函数,可以重载为类的友元函数和普通函数. 通常重载输出运算符的第二个行参是const的,因为输出一个类不许要更改它: 但是重载输入运算符的第二个行参必须是非const的,否则无法赋值. 重载的基本方法如下: //重