重載new,delete運算符 new,delete在c++中也被歸為運算符,所以可以重載它們。 new的行為: 先開闢記憶體空間 再調用類的構造函數 開闢記憶體空間的部分,可以被重載。 delete的行為: 先調用類的析構函數 再釋放記憶體空間 釋放記憶體空間的部分,可以被重載。 為什麼要要重載它們? 有 ...
重載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);
}