歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

C++拾遺--new delete 重載

前言

new和delete是操作動態內存的一對操作。對它們重載可以對內存管理進行有效的定制。

正文

1.局部重載

特別針對某一類型,對new和delete進行重載,可以對該類型對象的動態創建實行監控。如下代碼:

代碼一

#include <iostream>
using namespace std;
class MyClass
{
public:
 MyClass()
 {
  cout << "MyClass()" << endl;
 }
 ~MyClass()
 {
  cout << "~MyClass()" << endl;
 }
 void *operator new(std::size_t size)
 {
  cout << "局部new call" << endl;
  void *mem = malloc(size);   
  if (mem)    //內存分配失敗,則返回0
   return malloc(size);
  else
   throw bad_alloc();    //內存分配失敗,拋出異常
 }
 void operator delete(void *ptr)
 {
  cout << "局部delete call" << endl;
  //不為空,則調用free釋放內存
  if (ptr)
  {
   free(ptr);
  } 
 }
};
int main()
{
 cout << "******局部new delete重載演示***by David***" << endl;
 MyClass *my = new MyClass;
 delete my;
 cin.get();
 return 0;
}

運行

運行結果表明

表達式new整合了內存分配和構造函數。先調用malloc分配內存,然後調用指定類型並相匹配的構造函數初始化該段內存。

表達式delete整合了析構函數和內存釋放。先調用類的析構函數釋放資源,後調用free釋放分配的內存。

代碼二

下面一個例子提供了對內存分配進行監控的一種方法。

#include <iostream>
using namespace std;
class MyClass
{
public:
 //count記錄未釋放的對象個數
 static int count;
 int a;
 MyClass()
 {
  cout << "MyClass()" << endl;
  count++;
 }
 ~MyClass()
 {
  cout << "~MyClass()" << endl;
  count--;
 }
 //new 局部重載
 void *operator new(size_t size)
 {
  cout << "局部new call" << endl;
  void *mem = malloc(size);    //內存分配失敗,則返回0
  if (mem)
   return malloc(size);
  else
   throw bad_alloc();    //內存分配失敗,拋出異常
 }
 //new[] 局部重載
 void *operator new[](std::size_t size)
 {
  cout << "局部new[] call" << endl;
  void *mem = malloc(size);    //內存分配失敗,則返回0
  if (mem)
   return malloc(size);
  else
   throw bad_alloc();    //內存分配失敗,拋出異常
 }
 //delete 局部重載
 void operator delete(void *ptr)
 {
  cout << "局部delete call" << endl;
  //不為空,則調用free釋放內存
  if (ptr)
  {
   free(ptr);
  }
 }
 //delete[] 局部重載
 void operator delete[](void *ptr)
 {
  cout << "局部delete[] call" << endl;
  //ptr不為空,則調用free釋放內存
  if (ptr)
  {
   free(ptr);
  }
 }
};
int MyClass::count = 0;
int main()
{
 cout << "******new delete 局部重載演示***by David***" << endl;
 cout << "起始MyClass::count = " << MyClass::count << endl;
 MyClass *my = new MyClass;
 delete my;
 cout << "-----------------" << endl;
 MyClass my1;
 cout << "-----------------" << endl;
 MyClass *mys = new MyClass[5];
 cout << "MyClass::count = " << MyClass::count << endl;
 delete[]mys;
 cout << "MyClass::count = " << MyClass::count << endl;
 cin.get();
 return 0;
}

運行

2.全局重載

對全局的new和delete重載可以監控所有類型的內存分配。

#include <iostream>
#include <string>
using namespace std;
class MyClass
{
public:
 MyClass()
 {
  cout << "MyClass()" << endl;
 }
 ~MyClass()
 {
  cout << "~MyClass()" << endl;
 }
 void *operator new(std::size_t size)
 {
  cout << "MyClass::new重載" << endl;
  void *mem = malloc(size);
  if (mem)
   return mem;
  else
   throw bad_alloc();
 }
 void *operator new[](std::size_t size)
 {
  cout << "MyClass::new[]重載" << endl;
  void *mem = malloc(size);
  if (mem)
   return mem;
  else
   throw bad_alloc();
 }
 void operator delete(void *ptr)
 {
  cout << "MyClass::delete重載" << endl;
  if (ptr)
  {
   free(ptr);
  }
 }
 void operator delete[](void *ptr)
 {
  cout << "MyClass::delete[]重載" << endl;
  if (ptr)
  {
   free(ptr);
  }
 }
};
//全局new重載
void *operator new(std::size_t size)
{
 cout << "全局new重載" << endl;
 void *mem = malloc(size);
 if (mem)
  return mem;
 else
  throw bad_alloc();
}
//全局new[]重載
void *operator new[](std::size_t size)
{
 cout << "全局new[]重載" << endl;
 void *mem = malloc(size);
 if (mem)
  return mem;
 else
  throw bad_alloc();
}
//全局delete重載
void operator delete(void *ptr)
{
 cout << "全局delete重載" << endl;
 if (ptr)
 {
  free(ptr);
 }
}
//全局delete[]重載
void operator delete[](void *ptr)
{
 cout << "全局delete[]重載" << endl;
 if (ptr)
 {
  free(ptr);
 }
}
int main()
{
 cout << "******全局/局部new和delete都進行重載***by David***" << endl;
 int *p = new int;
 delete p;
 cout << "-------------------" << endl;
 double *ds = new double[10];
 delete[]ds;
 cout << "-------------------" << endl;
 MyClass *my = new MyClass;
 delete my;
 cout << "-------------------" << endl;
 MyClass *mys = new MyClass[3];
 delete[]mys;
 cin.get();
 return 0;
}

運行

如果類型重新定義了new 和 delete,則調用局部的,否則調用全局的。

細節

  • operator new或operator new[]的返回類型必須是void*。
  • operator delete或operator delete[]的返回類型必須是void。
  • 類中重載的new和delete都是隱式static的。若顯式聲明,也不會出錯。
  • size_t就是unsigned int。當編譯器調用operator new時,把存儲指定類型對象所需的字節數傳遞給size_t的形參。當調用operator new[]時,就傳遞數組中所有元素的字節數。

 

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved