定位 new 表達式
盡管 operator new 函數和 operator delete 函數一般用于 new 表達式,然而它們畢竟是標準庫函的兩個普通函數,因此普通的代碼也可以直接調用它們。
在 C++ 早期版本中,allocator 類 還不是標準庫的一部分。應用程序如果想把內存分配與初始化分離開來的話,需要調用 operator new 和 operator delete。這兩個函數的行為與 allocator 的 allocate 成員和 deallocate 成員非常類似,它們負責分配或釋放內存空間,但是不會構造或銷毀對象。
與 allocator 不同的是,對于 operator new 分配的內存空間來說我們無法使用 construct 函數構造對象。相反,我們應該使用 new 的 定位 new(placement new) 形式構造對象。如我們所知,new 的這種形式為分配函數提供了額外的信息。我們可以使用定位 new 傳遞一個地址,此時定位 new 的形式如下所示:
new (place_address) type;
new (place_address) type (initializers);
new (place_address) type [size];
new (place_address) type [size] { braced initializer list }
釋義:
-
place_address必須是一個指針 - 在
initializers中提供一個(可能為空的)以逗號分隔的初始值列表,該初始值列表將用于構造新分配的對象。
當僅通過一個地址值調用時,定位 new 使用 operator new(size_t, void*) 分配內存。這是 一個我們無法自定義的 operator new 版本。該函數不分配任何內存,只是簡單地返回指針實參;然后由 new 表達式負責在指定的地址初始化對象以完成整個工作。事實上,定位 new 允許我們在一個特定的、預先分配好的內存地址上構造函數。
注意: 當只傳入一個指針類型的實參時,定位 new 表達式構造對象但是不分配內存。
定位 new 類似于 allocator 類的 construct 成員,但在它們之間也有一個重要的區(qū)別。我們傳遞給 construct 的指針必須指向同一個 allocator 對象分配的空間,但是傳給定位 new 的指針無須指向 operator new 分配的內存。實際上,傳給定位 new 表達式的指針甚至不需要指向動態(tài)內存。
顯式的析構函數調用
類似于定位 new 和 allocate 類一樣,對析構函數的顯式調用也與使用 destroy 一樣。我們既可以通過對象調用析構函數,也可以通過對象的指針或引用調用析構函數,這與調用其他成員函數沒有什么區(qū)別:
std::string *sp = new std::string("a value");
sp->~string(); // 調用析構函數銷毀對象,但是 sp 所指的內存沒有釋放
和調用 destroy 類似,調用析構函數可以銷毀對象但是不會釋放內存空間。因此我們可以反復利用這個內存空間。例如:
std::string *sp = new std::string("a value");
sp->~string();
sp = new std::string("new value"); // 重新使用 sp 所指的內存空間進行對象的構造
注意: 調用析構函數可以銷毀對象,但是不會釋放內存。
本文非原創(chuàng),內容摘錄自《C++ Primer 中文版(第 5 版)》,為了有更多的知識能夠傳播,請多多支持正版。