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

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM