天天看點

4 避免無用的預設構造函數

預設構造函數即沒有參數或所有參數都聲明了預設值的構造函數,可以在沒有任何外部資料下初始化對象。當類沒有聲明構造函數,編譯器會提供一個隐式預設構造函數。

借由預設構造函數建立的對象,其成員變量被初始化為固定的或是不确定的值,不能保證類的成員都被正确初始化。當類有一個無意義的預設構造函數,未能将所有部分正确初始化,類的成員函數則必須另外測試成員變量是否是有效的,付出了更多的代碼,是以應盡量避免。

沒有預設構造函數的類必須傳入外部資料來構造,讓人相信這個類的對象會被正确的實作,但也存在使用上的限制。

對象數組

直接聲明對象數組,會調用類的預設構造函數,如果沒有則必須為數組初始化傳參。

Class array[10];//error: no matching function for call to "Class::Class()"
Class array[10] = {{val1, val2, ...}, ...};//correct
           

但對于堆配置設定的對象數組(

new []

),并不能通過上述方式傳參。

Class * array = new Class[2];//error: no matching function for call to "Class::Class()"
Class * array = new Class(value)[2];//error: 文法錯誤
           

可以通過(類)指針數組來替代對象數組,并逐個為指針配置設定堆記憶體。對應的,在釋放時也需要逐個調用析構函數。

Class * array[10];
for(auto it : array)
{
    it = new Class(value);
}
           

指針數組的方式使用了額外的記憶體儲存指針,可以使用

placement new

方法為數組配置設定

raw memory

,在記憶體中構造對象。

int size = 10;
void * memory = operator new[](size * sizeof(Class));//類似malloc傳回未處理的堆記憶體塊位址
Class * array = static_cast<Class *>(memory);
for(int i=0; i<size; ++i)
{
    new (&array[i]) Class(1, 2);//在已配置設定的位址上構造對象
}
           
for(int i=0; i<size; ++i)
{
    array[i].~Class();
}
memory = static_cast<void *>(array);
operator delete[] (memory);
           

在模闆容器中使用

pair<int, Class> pa;//error: no matching function for call to 'std::pair<int, Class>::pair()'
           

虛基類