標籤:c++
C++ new 的基本和進階用法推薦文章 http://kelvinh.github.io/blog/2014/04/19/research-on-operator-new-and-delete/new 的基本用法
int *a = new int[5];class A {...} //聲明一個類 AA *obj = new A(); //使用 new 建立對象delete []a;delete obj;
這裡我們注意,new int[5] 僅僅分配了空間, 但是 new A(),不僅僅為對象obj在隊上分配了空間, 而且還調用了 A的建構函式,產生了這個對象。
所以 new A() 這樣方式的功能如下:
- 在堆上分配空間
- 在分配的空間上調用對象的建構函式
(這也是 new 和 malloc的主要區別,是否調用建構函式)
同理: 在調用 delete obj
的時候:
1. 首先調用 這個對象 的解構函式
2. 然後釋放這個對象的空間
new 的升級版本 (version 1)
從上面可以看到:new 的功能是 1. 分配空間, 2 調用建構函式。 那麼到底是如何?的呢?
其實 C++ 規定 new 的 這 兩個功能分開實現:
1. 分配空間: 調用函數 operator new 來實現。
2. 調用建構函式: 調用 placement new 來實現。
現在有三個 new 了,第一個new就是我們常說的new, 這個new 調用 接下來的兩個new 來實現它的功能。 (我們稱這個 new 為, new operator,叫做“new 運算式”,因為operator 在 new 後面,所以 叫做 “new 運算式”,也就是關鍵字)
new關鍵字 會調用 operator new 分配空間: 這裡 operator new 是一個全域的函數,寫在一個檔案中。當使用 new 關鍵字 的時候,編譯器會自動找到這個函數,並且調用這個函數:這個函數的聲明如下:
// 全域 operator newvoid * operator new(std::size_t size) throw(std::bad_alloc) { if (size == 0) size = 1; void* p; while ((p = ::malloc(size)) == 0) { //採用 malloc 分配空間 std::new_handler nh = std::get_new_handler(); if (nh) nh(); else throw std::bad_alloc(); } return p;}// 對應的全域 operator delete 採用 free 釋放空間void operator delete(void* ptr) { if (ptr) ::free(ptr); //採用 free 釋放空間。}
這個 operator new
函數稱為 全域 operator new 。 (這裡稱為 全域 主要是因為 每個類 還可以 重載 自己的 operator new()
函數)
全域 operator new 分配空間
從上個例子中可以看到, 全域 operator new 分配空間,簡單的調用了 malloc()
函數來分配空間。 並沒有做任何初始化工作。
現在問題來了: 已經有了一段分配好的空間 ,如何在這個空間上 調動這個類的建構函式,從而真正的建立一個對象呢? (你需要對 對象的 記憶體模型 有一定的瞭解)。 解決方案是: placement new
placement new 調用建構函式
placement new 的功能就是 在一個 已經分配好的空間上,調用建構函式,建立一個類。
placement new 就這一個用法,知道如何用就可以了,它不是一個(寫在檔案中)函數,是編譯器編譯時間候做的事情。
用法如下:
void *buf = // 在這裡為buf分配記憶體Class *pc = new (buf) Class();
舉例子:
class A {...} //聲明一個 類 A void *buf = malloc(sizeof(A)); //簡單地分配空間。 A *ojb = new (buf)A(); // 在分配的空間上調用建構函式。
現在問題來了: 這裡 的空間可以是任意的空間嗎,答案是的! 這裡的 “已經分配好的空間” 可以是任何的空間,比如說 可以是棧上的空間!
class A {int a;} int buf[sizeof(A)]; //在棧上,分配一個數組 A *obj = new(buf) A(); //在這個數組上構造一個 對象 A。
new 的升級版本 (version 2)
我們稱上一個 operator new 為 全域operator new ,因為它是一個檔案中的函數。
1. 於是我們就可以對 operator new 進行重載了:
2. 重載之後,我們可以在其中自己進行記憶體配置。(比如說,不使用 malloc進行實現)
但是重載 operator 必須非常的注意!
文章說的非常好, 有非常多的注意事項! 有好處也有壞處,
陳碩的文章 說的也非常好! 值得一看,看不懂別怪我。
這裡的升級版本是: 可以在類中重載 operator new 和 placement new。 這個需要在 google 上搜尋一下。
new 的用法!
當我們自己重載了 new 之後,就可以進行記憶體管理了,必須說構造一個記憶體池! 當然,這是下一篇文章的內容了。
(文章還會在不斷的修改的)
C++ new 的用法 (總結)