new
和delete
只能一次分配釋放一個對象,一些場合,我們需要一次為很多對象分配內存,為了支持這種需求,C++標準庫提供了兩種方法:new
和allocator
。
1 new和數組
一些基本的語法
int *a = new int[get_size()];
int *a = new string[100]();
int *a = new string[10]{"a","b","c",string(3,'x')};
typedef int att[10];
int *a = new att;
delete []a;
智能指針和動態數組可以用unique_ptr
管理動態數組,語法如下:
unique_ptr<int[]> up(new int[10]);
up[i] = 10;
up.release();//自動調用delete[]釋放指針
\\此時,指向數組的unique ptr不支持成員訪問運算符即 . 和 -> 運算符
\\其他unique ptr操作保持不變
與unique_ptr
不同,shared_ptr
不支持直接管理動態數組,需要自己定義的刪除器:
shared_ptr<int> sp(new int[10],[](int *p){delete []p;});//此處使用了lambda表達式
shared_ptr未定義下標運算符,并且不支持指針算術運算符
*(sp.get()+i) = i; //i為我們要訪問的下標
2 allocator類
new
和delete
有一些靈活性的局限,將內存分配(釋放)和對象構造(析構)組合在了一起,有時這會造成浪費。
標準庫allocater
類定義在頭文件memory
中,它幫助我們將對象構造和內存分配分離開,它提供一種類型感知的內存分配方法,它分配的內存是原始的,未構造的。
//定義allocator對象,它可以為類型為T的對象分配內存
allocator<T> a;
//分配一段原始的、未構造的內存,保存n個類型為T的對象
auto p = a.allocate(n);
//在p指向的內存中構造一個對象
a.construct(p,args);
//對p指向的對象執行析構函數
a.destroy(p);
//釋放從T*指針 p中地址開始的內存,這塊內存保存了n個對象;
//p必須先用allocate分配返回的指針,并且需要使用destroy析構對象后才能調用deallocate
a.deallocate(p,n);
以下為使用示例:
allocator<string> alloc;
auto const p = alloc.allocate(n);//分配n個未初始化的string
auto q = p;
alloc.construct(q++);//*p為空字符串
alloc.construct(q++,10,'c');//*p為cccccccccc
alloc.construct(q++,"h1");//*p為hi
while(q!=p)
alloc.destroy(--q);//被銷毀后,可以重新構造,注意是前置--
alloc.deallocate(p,n);
標準庫還為allocator
類定義了兩個伴隨算法,用來進行拷貝和填充操作:
//從迭代器b和e指出的范圍中拷貝元素到迭代器b2開始的未構造內存中
uninitialized_copy(b,e,b2);
//將從迭代其b開始n個元素拷貝到迭代器b2開始的內存中
uninitialized_copy(b,n,b2);
//在迭代器b和e指出的范圍中創建t的拷貝對象(多個)
uninitialized_fill(b,e,t);
//從b開始的內存中創建n個t對象
uninitialized_fill(b,n,t);