C++易混知識點3. New Operator, Operator New, Placement New 實例分析,比較區別

我們知道,C++中引入了New 這個內置符號,很大方便了指針的使用,程序員不必關注與這塊堆上新分配的內存是如何來的,如何初始化的,然後如何轉換爲我們想要的類型指針的。現在,我們重點來分析下這個NEW內置符號背後的步驟和所調用到的函數。這裏面涉及到new operator, operator new, placement new.


轉載請註明出處: http://blog.csdn.net/elfprincexu


1. New Operator (__type__ * a = new a();)

C 語言當中,我們在新申請一塊內存的時候,通常使用的是malloc, 通常通過malloc(size_t size)來獲得一塊未初始化的raw memory。然後一般情況下我們會對該部分空間初始化(memset or memcpy)。

C++語言引入了new 操作符,極大地方便了使用,它一下子把C語言中的好幾個步驟一下完成了,讓我們覺得神奇的是,不必去深究其中的調用。

其實,new operator主要做了以下三個步驟的:

std::string* str = new std::string("memory management");// 例如,我們想申請一個新的string空間,其中空間並被初始化爲“memory management”,並且該空間由一個stringlei類型的指針來指向,並把它返回給str。


1. 第一步,調用了 operator new 函數, operator new函數的作用 僅僅 是申請一塊未被初始化的內存。

函數申明爲:void* operator new (size_t size)

void* memory = operator new (sizeof("memory management"));// 申請足夠大小的內存空間

2. 第二部,調用string 構造函數,在該未初始化的空間上初始化,也就是“memory management”

call string::string("memory management") on memory*

3. 第三部,將該指針轉換爲指定的想要的指針類型

string* str =  static_cast<std::string*> (memory);


  總結下來: 

(1)通過operator new申請內存

(2)使用placement new調用構造函數(簡單類型忽略此步)

(3)返回內存指針


2. operator new (該函數僅僅 申請足夠大小的內存,可以被重載)

void * operator new (size_t size);

舉個例子來講:

// operator new example
#include <iostream>
#include <new>
using namespace std;
 
struct myclass {myclass() {cout <<"myclass constructed\n";}};
 
int main () {
 
   int * p1 = new int;
// same as:
// int * p1 = (int*) operator new (sizeof(int));
 
   int * p2 = new (nothrow)int;
// same as:
// int * p2 = (int*) operator new (sizeof(int),nothrow);
 
   myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types)
 
   new (p3) myclass;   // calls constructor
// same as:
// operator new (sizeof(myclass),p3)
 
   return 0;
}

重載operator new,

void * operator new (size_t size, string str);// 比如我們添加一個形參string, 用來輔助輸出

調用

Base *b = new (“Operator new overload example”) Base;// str 形參放在new 後的掛號裏面,

same as :

Base *b = (Base* ) ( operator new (sizeof(Base), "Operator new overload example") );

class Base {
public:
  Base() { }
 
  void *operatornew(size_t size, string str ) {
    cout << "Logging an allocation of " << size << " bytes for new object'" << str << "'" << endl;
    return malloc( size );
  }
 
  int var;
  double var2;
};
 
 
Base* b = new ("Base instance 1") Base;

      輸出: Logging an allocation of 12 bytes for new object 'Base instance 1'


3. Placement new. void* operator new ( size_t size, void* ptr) ;// ptr 會被返回,因爲我們已經指定在已知的內存上

歸根結底來講,placement new 是operator new 的一種特殊重載,它不分配內存,只是調用合適的構造函數在ptr所指的地方構造一個對象,之後返回實參指針ptr。

例如:

myclass* p3 = static_cast<myclass*> ( operator new (sizeof(myclass));// p3 已經指定一塊足夠放下myclass對象的空間,該空間未初始化,

new (p3) myclass;// placement new, 在指定的p3空間上,call constructor myclass()來初始化該空間,並且返回p3.

// operator new example
#include <iostream>
#include <new>
using namespace std;
 
struct myclass {myclass() {cout <<"myclass constructed\n";}};
 
int main () {
   myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types)
 
   new (p3) myclass;   // calls constructor
// same as:
// operator new (sizeof(myclass),p3)
 
   return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章