2014-02-21 83 views
3

我讀關於如何實現一個ArrayList我的數據結構的書,我對擦除功能如下代碼:爲什麼在此代碼中調用析構函數?

template<typename T> 
ArrayList<T>::~ArrayList() { 


delete [] dynArr; 


} 

我:

template <typename T> 
void ArrayList<T>::erase(int index) { 

    //Delete the element whose index is "index" 
    //Throw illegalIndex exception if no such element 
    checkIndex(index); 



    std::copy(dynArr+ index + 1, dynArr + listSize, dynArr + index); 

    dynArr[--listSize].~T(); //invoke destructor 


} 

的析構函數的定義對於那裏到底發生了什麼感到困惑。是不是隻有在需要刪除整個數組時需要刪除的析構函數?

+1

您可以調用dynArr的元素的析構函數而不是類的析構函數ArrayList – Felix

+0

請注意,在現實世界中幾乎不應該看到這種類型的代碼。讓編譯器在99.99%的時間內爲你調用析構函數。 – jia103

回答

2

T的析構函數(的ArrayList<T>未析構函數),並因爲使用特殊的placement new operator

其中在堆上一個預先分配的陣列上創建,而不是單獨類型T的對象,所以當一個人很可能被刪除沒有必要釋放任何內存,但你想調用析構函數,所以狀態將被清除

放置new運算符允許構造給定內存地址的對象。這允許庫(比如std :: vector)爲將來的構造分配一塊內存。並且使用在該塊上的特定位置放置新運算符構建類實例:void* operator new (std::size_t size, void* ptr) throw();

但是,當您要刪除對象時,您不能delete因爲它不擁有內存,但仍然調用析構函數它會清理自己的狀態。 AFAIK這是唯一的使用情況是適當的調用析構函數直接

編輯 說明發表評論爲什麼調用析構函數的最後一個對象上,而不是指數:

STD: :副本將「複製」的使用他們的賦值運算符還挺像這樣的對象:

template<class InputIterator, class OutputIterator> 
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) 
{ 
    while (first!=last) { 
     *result = *first; 
     ++result; ++first; 
    } 
    return result; 
} 

所以運營商=物體將被稱爲很多次。 位置索引處的對象將被索引+ 1處的對象覆蓋。您期望適當的分配實施既釋放自己的資源,又準確地複製目標資源。 當你完成這個操作時,你會得到一個正確的數組,其中最後兩個元素是相互精確的副本,並且你使用析構函數來清理最後一個元素。

注意:這樣做的性能大概可以考慮改進C++ 11移動語義,而不是性病::複製(如升壓移動算法boost::move

NOTE2:如果你持有一個指針,指向一個元素列表在一個位置>索引它會在這種改變後指向錯誤的元素。

+0

嗯..所以析構函數只是照顧在我選擇在函數中刪除索引的元素?因爲當我讀取dynArr [ - listSize]時,它使我認爲它正在銷燬dynArr [ - listSize]上的元素,但這與銷燬作爲參數的索引處的元素不同。不應該析構函數首先銷燬元素,然後使用副本將元素移動一個位置?@edsh – FrostyStraw

+0

請參閱編輯,以瞭解爲什麼代碼在「去除」最後一個元素而不是索引處的元素中是正確的。 但是,如果有人持有一個指向ArrayList中的元素的指針,那麼在此更改之後它將是錯誤的元素 – odedsh

相關問題