控制記憶體分配----過載new和delete & 定位new表示式
文章來源C++ Primer 第五版
過載new和delete
注:
1、瞭解operate new和operate delete各自的功能;2、解構函式只是銷燬物件,而不會釋放掉記憶體,這也就解釋了delete表示式為什麼是執行了兩步。
關於noexcept有關知識,請參考<http://blog.csdn.net/qianqin_2014/article/details/51321631>
定位new表示式
關於allocator的知識,請參考<http://blog.csdn.net/qianqin_2014/article/details/51323555>
定位new表示式的應用
1 經典示例:
#include <iostream>
#include <new>
const intchunk = 16;
class Foo
{
public :
int val( ) { return _val; }
Foo( ) { _val = 0; }
private :
int_val;
};
//預分配記憶體,但沒有Foo物件
char*buf = new char[ sizeof(Foo) * chunk ];
int
main( void )
{
//在buf中建立一個Foo物件
Foo*pb = new (buf) Foo;
//檢查一個物件是否被放在buf中
if ( pb->val() == 0 )
{
cout <<"new expressio worked!" <<endl;
}
//到這裡不能再使用pb
delete[] buf;
return 0;
}
但我不瞭解這種“定位new表示式”相對於一般的new的優點是什麼?它的用法比一般的new物件要複雜!
2使用定位new表示式作用
1)placement new的作用就是:建立物件但是不分配記憶體,而是在已有的記憶體塊上面建立物件。用於需要反覆 建立並刪除的物件上,可以降低分配釋放記憶體的效能消耗。
2)定位new表示式,允許程式設計師將物件建立在已經被分配好的記憶體中,new表的式的形式如下:
new (place_address) type
new (palce_address) type (initializer-list)
place_address必須是個指標,指向已經分配好的記憶體。為了使用這種形式的new表示式,必須包含標頭檔案<new>。
定位new表示式不能呼叫delete刪除 placement new的物件,需要人為的呼叫物件的解構函式,並且人為的釋放掉佔用的記憶體。
#include <iostream>
#include <new>
using namespace std;
const int chunk = 16;
class Foo
{
public:
int val(){return _val;}
Foo(){_val=0;}
private:
int _val;
};
int main()
{
// 預分配記憶體buf
char *buf = new char[sizeof(Foo) * chunk];
// 在buf中建立一個Foo物件
Foo *pb=new (buf) Foo;
// 檢查一個物件是否被放在buf中
if(pb->val()==0) cout<<"new expression worked!"<<endl;
// 這裡不存在與定位new表示式匹配的delete表示式,即:delete pb, 其實只是為了
// 釋放記憶體的話,我們不需要這樣的表示式,因為定位new表示式並不分配記憶體。
// 如果在解構函式中要做一些其他的操作呢?就要顯示的呼叫解構函式。
// 當程式不再需要buf時,buf指向的記憶體被刪除,它所包含的任何物件的生命期也就
// 都結束了。
delete[] buf;
return 0;
}定位new表示式的應用:在我們的程式中,首先使用malloc為物件分配空間,然後通過定位new表示式將物件建立在已經被分配好的記憶體中,完成建構函式的呼叫。
3)“new (start) Screen;”這是定位new操作
Screen *ps = new (start) Screen;
表示在已經開闢好的記憶體區start中為堆物件Screen申請一個記憶體
也就是說,如果start佔100個位元組,你現在從它的第1個位元組開始,往裡面寫入Screen,這樣做今後要釋放記憶體的時候有麻煩,如果Screen裡面有指標,並開闢了空間,那麼delete ps會呼叫析構函 數,然而在釋放指標變數所佔的記憶體空間時也釋放了為物件所分配的記憶體空間,所以start中的那塊記憶體也丟失了,因為ps也指向了start.所以要避免這種情況,就要先ps->~Screen()這樣顯示的呼叫Screen的解構函式,再delete
[]start。
---------------------
作者:烽火前秦路
來源:CSDN
原文:https://blog.csdn.net/qianqin_2014/article/details/51320775
版權宣告:本文為博主原創文章,轉載請附上博文連結!