第十六章 內存管理 ===高質量C/C++編程指南

New的3種使用方式:

Plain new // nothrow new //  placement new


Plain new :

                void* operator(std::size_t)throw(std::bad_alloc);

                void operator delete(void*)throw();

標準C++修訂new的語義,plain new在失敗後拋出異常std::bad_alloc而不是返回NULL。所以通過其返回值來判斷其返回值是徒勞的。 

char* getmemory(unsigned long len)
{
    char* p=new char[len];
    return p;
}
int main()
{
    try{
       char* p=getmemory(10000000000000000000);
       delete [] p;

    }
    catch(const std::bad_alloc &ex){
       cout<<ex.what()<<endl;
    }
    return 0;
}


Nothrow new:

                    顧名思義,不拋出任何異常的運算符,Nothrow new失敗返回NULL,所以使用時就不必設置異常處理器,用if檢查是否爲NULL即可。

                   void* operator new(std::size)_t,const std::nothrow_t&)throw();

                   void operator delete(void*)throw();

nothrow帶有一個參數,類型爲nothrow_t <NEW> 的一個全局const對象,作爲標誌啞元。

char* getmemory(unsigned long len)
{
    char* p=new(nothrow) char[len];
    return p;
}
int main()
{

       char* p=getmemory(10000000000000000000);
        if(!p) cout<<"alloc failed!"<<endl;
       delete [] p;

        return 0;
}

placement new/delete

                       placement new在一塊已經分配好的內存上面重新構造對象或對象數組,不用擔心分配失敗,因爲根本沒有分配。它所做的就是調用對象的構造函數。在<NEW>中定義原型如下:

                     void* _operator new(size_t,void*)

                     void* _operator delete(void*,void*)

 用法: typename *q=new(p) typename; 將p轉換爲目標類型的指針q;

因此p和q相等。

#include <iostream>
#include<NEW>
using namespace std;
char* getmemory(unsigned long len)
{
    char* p=new(nothrow) char[len];
    return p;
}
class A{
           int a;
public:
          A(int a=0):a(a){cout<<"hhaha"<<endl;}
          int getnum()const{return a;}
          ~A(){}
};
int main()
{

        char* p=getmemory(100);
        if(!p) cout<<"alloc failed!"<<endl;
         double* q=new(p)double(3);
         cout<<*q<<endl;

        A* r=new(p)A(10);
        r->A::~A();
        delete p;

        return 0;
}
用途:反覆使用一塊較大的動態分配成功的內存來構造不同類型的對象或者他們的數組,比如,可以先申請一個足夠大的字符數組,然後當需要時在它上面構造不同類型對象或者其數組。

注意:使用placement new構造起來的對象或者數組,要顯式的調用他們的析構函數來銷燬(析構函數並不釋放對象的內存),因爲對象或對象數組的大小並不等於原來分配內存的大小。因此使用delete會內存泄露。




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