2013-10-25 113 views
1

我正在嘗試創建一個動態分配的數組,該數組在填充時會創建一個足夠大的新數組,以容納所有數據並將舊數組中的所有值複製到新數組中。我在我的append函數中做了一個動作,當它被動態地分配一個新的數組並指向它的tmp時,然後將值從arr [i]移動到tmp [i]。但是,我想知道在完成它之後是否需要刪除tmp?因爲當我嘗試在不刪除tmp的情況下打印數組的內容時,它打印得很好,但是當我刪除tmp時,事情開始變得很奇怪,並且內容不再以他們應該的方式打印。這裏是我的代碼:創建動態分配的數組

ArrayList::ArrayList(int initsize): last(0), size(initsize), origsize(initsize) 
{ 
    arr = new int[size]; 
} 

ArrayList::ArrayList() 
{ 
    last = 0; 
    size = 16; 
    origsize = 16; 
    arr = new int[size]; 
} 

void ArrayList::append(int value) 
{ 
    if (last<size) { 
     arr[last] = value; 
    } 

    last++; 

    if (last == size) { 

     int* tmp = new int[size+origsize]; 
     int i = 0; 

     for (i=0; i<(size+origsize); i++) 
      tmp[i] = arr[i]; 

     size = size+origsize; 
     arr = tmp; 
     arr[last] = value; 

     //delete tmp; 
    } 
} 
+0

只要確保你刪除在正確的地方。您的評論會刪除'tmp',但我認爲您應該在'arr = tmp'行之前刪除'arr'。 – Sjlver

+0

......我認爲這是學術性的,因此把整個事情拋出來用於'std :: vector '是不可能的。 – WhozCraig

回答

2

的問題是在這裏:

for (i=0; i<(size+origsize); i++) { 

     tmp[i] = arr[i]; 

    } 

改編的長度是「大小」,但您要訪問的元素超越它。它會導致未定義的行爲。

IMO,你不應該嘗試在你的程序中重新調整數組的大小。如果您想要一個動態大小的容器,請改用std :: vector。

編輯:正如其他人所指出的那樣,如果這是學術的理由,那麼你可以修改代碼類似如下:現在

void ArrayList::append(int value) 
{ 
    if (last<size) { 
     arr[last] = value; 
     last++; 
    } else { // last shall be equal to size. 

     int* tmp = new int[size+origsize]; 
     int i = 0; 

     for (i=0; i<(size); i++) // delete + originalsize 
      tmp[i] = arr[i]; 

     size = size+origsize; 
     int* newTemp = arr; // make a new pointer point to where arr was pointing 
     arr = tmp;   // make arr point to where tmp was pointing. 
     //tmp = newTemp; // You do not need this statement. 
     arr[last] = value; 
     last++; 
     delete [] newTemp; // delete the old array memory block 
    } 
} 
+0

是的,我寧願使用我相信的(我們沒有在課堂上學過),但是我們的教授特別想要我們......這樣做是爲了我們自己,我想教我們一些教訓,不明白。他不喜歡我們使用我們沒有創建的任何函數ourselvs – FrostyStraw

+0

我認爲他正在試圖實現ArrayList,它只是使用數組並調整它們的大小。 –

2

你的編曲是TMP。我的意思是他們都指向一個新的陣列。你需要刪除舊的。做

int* old = arr; 
arr = tmp; 
delete [] old; 
arr[last] = value; 
+0

如果我正確讀取它。當您刪除arr時,您將刪除舊數組。然後你問tmp指出什麼arr指向..這是什麼,因爲arr被刪除... – FrostyStraw

+0

我的壞。編輯。 –

+0

所以,如果我只是刪除舊的,我只是刪除名爲舊的指針。但是要刪除舊指向的實際數組,我需要刪除[]舊的? – FrostyStraw

0

新陣列指向舊的。

因此,在你的代碼(withou修改),你不能刪除ARR

0

你一定要刪除tmp目錄,因爲,因爲你已經使用它聲明爲一個指針*。一旦離開作用域(離開下一個),它將不會自動釋放,並且會導致內存泄漏。關於指針的有用信息here以及如何聲明它將其放在堆上並要求手動刪除它。 由於您正在嘗試在此創建動態數組。我想你想讓arr成爲指針,而不是tmp。 結賬this c++ tutoriall

0

您正在使用newdelete,這是C-ish。在C++中,您應該信任現有的工具來爲您處理內存。我們可以使用std::vector,雖然它會妨礙練習;相反,我建議我們使用std::unique_ptr

class ArrayList { 
public: 
    ArrayList(); 

    explicit ArrayList(size_t i); 

    void append(int i); 

private: 
    size_t last;     // position to append to 
    size_t size;     // current size of the array 
    std::unique_ptr<int[]> array; // actual array of data 
}; // class ArrayList 

注:而不是使用origsize,我們可以雙擊每個擴展的能力,從而贏得了append「分期常量」的複雜性。

// We first need a creation function for raw memory: 
std::unique_ptr<int[]> allocate(size_t n) { 
    return std::unique_ptr<int[]>(new int[n]); 
} 

// Now, the default constructor 
ArrayList::ArrayList(): last(0), size(16), array(allocate(size)) {} 

// And the user constructor 
ArrayList::ArrayList(size_t i): last(0), size(i), array(allocate(size)) {} 

有了這一點的方式,讓我們專注於append

void ArrayList::append(int e) { 
    if (last >= size) { // need to reallocate 
     std::unique_ptr<int[]> neo = allocate(size*2); 

     for (size_t i = 0; i < size; ++i) { 
      neo[i] = array[i]; 
     } 

     size *= 2; 
     swap(neo, array); 
    } // reallocation 

    array[last] = e; 
    ++last; 
} 

它是如何從你的代碼不同:

  1. 當從一個陣列複製到另一個,我只複製size元素(您正在閱讀的界限)
  2. 我不手動處理內存,而是我將內存處理推遲到std::unique_ptr
  3. append中插入e之後沒有必要重新分配,您可以等待已經用完的地方。
  4. 採用分期常量複雜性append更高效