2017-10-19 99 views
2

我在C++學習指針並遇到一個非常奇怪的問題。我們的任務是爲我們自己的類編寫我們自己的push_back函數,它包含一個整數數組。刪除數組只偶爾失敗

我有以下簡單功能:

void IntRow::push_back(int value){ 
    int *elements_temp = new int[size+1]; 
    for (int i = 0; i <= size; i++){ 
     elements_temp[i] = elements[i]; 
    } 
    elements_temp[size + 1] = value; 
    elements = new int[size+1]; 
    for (int i = 0; i <= size+1; i++){ 
     elements[i] = elements_temp[i]; 
    } 
    delete [] elements_temp; 
    size++; 
} 

然而這失敗,但上線只是偶爾delete [] elements_temp;

,出現以下錯誤信息:

incorrect checksum for freed object - object was probably modified after being freed. 

爲什麼這是怎麼發生的,爲什麼它只發生有時

評分:我是否真的必須免費elements_temp或者在功能存在之後是否被釋放?

+0

'elements = new int [size + 1];'你在這裏失去了我。你爲什麼要分配**另一個**緩衝區? – StoryTeller

+0

因爲我想將臨時數組中的所有內容都複製到新元素數組中以實際保留舊值+我們正在推動的新值。 –

+2

'elements_temp [size + 1] = value;'是未定義的行爲。 –

回答

5

elements_temp[size + 1] = value;的行爲未定義,因爲您正在訪問數組邊界之外的元素。

這種未定義的行爲表現爲偶然的程序崩潰。

是的,你需要明確地調用delete[]你自己從new[]返回的指針。 (出於興趣,誰在elements上呼叫delete[]?)

或者,使用std::vector<int>

+1

你的最後一句話是輕微的輕描淡寫。 –

+0

但我開始聲明: 'int * elements_temp = new int [size + 1];' '[size + 1]'如何越界? –

+2

Cuz元素從0開始索引,innit。你知道C++不是Fortran。 – Bathsheba

1
int *elements_temp = new int[size+1]; 
for (int i = 0; i <= size; i++){ 
    elements_temp[i] = elements[i]; 
} 
elements_temp[size + 1] = value; 

您分配elements_temp存儲size+1整數。這個數組內的有效索引從0size而不是size+1),因爲在C++中索引是基於0的。 所以,你寫以外數組界限在上面的最後一行。這是undefined behavior,這可能是你的問題的原因。

你可能要爲size+1整數分配房間,並複製先前的整數到新數組是什麼,然後添加上一個新的元素:

// Allocate room for size+1 integers: 
const int newSize = size + 1; 
int* elements_temp = new int[newSize]; 

// Copy the old array data to the new array. 
// Note: i < size, *not* <= ! 
for (int i = 0; i < size; i++) { 
    elements_temp[i] = elements[i]; 
} 

// Write the new item at the end of the array. 
// Note: The index is "size", *not* "size+1" 
elements_temp[size] = value; 

// Update the size data member in your array class to store the new size 
size = newSize; 

此外,你應該deleteelements陣列之前將新創建一個,如:

// Get rid of old array memory 
delete[] elements; 

// If you don't call delete[] above, you will *leak* the old elements array 

// Take ownership of the new array 
elements = elements_temp; 

更好地分配政策

我想補充的是,每次分配數組你這是一個非常低效的策略中添加的項目。更好的方法(例如使用由標準std::vector容器)是預先分配一些存儲器,創造了一種可用容量,然後分配一個陣列和複製舊的數據到新的陣列,只有當舊向量沒有更多的空間(換句話說,只有當沒有更多的「容量」可用時)。

事實上,動態內存分配new[]是昂貴的,最好是最小化它們。 (雖然這種容量優化可能或可能不是你的老師在這個學習過程中想要的。)

+0

謝謝,現在相當清楚!爲什麼你爲新尺寸指定'const'?比只使用'size + 1'更好嗎? –

+0

不客氣。我很高興我有一些幫助。我認爲用'const'定義一個只讀變量(即一個你不能修改的變量)並在其中存儲新的大小值,使得代碼更清晰並且比在幾個地方重複「size + 1」更少的bug發生並且可能在某處丟失了「+1」......無論如何,隨意選擇你覺得更具可讀性的東西。 –

+0

哦,這不是一個性能收益問題嗎?他們執行的方式是一樣的嗎? –