删除数组只偶尔失败
我在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
或者在功能存在之后是否被释放?
elements_temp[size + 1] = value;
的行为未定义,因为您正在访问数组边界之外的元素。
这种未定义的行为表现为偶然的程序崩溃。
是的,你需要明确地调用delete[]
你自己从new[]
返回的指针。 (出于兴趣,谁在elements
上呼叫delete[]
?)
或者,使用std::vector<int>
。
你的最后一句话是轻微的轻描淡写。 –
但我开始声明: 'int * elements_temp = new int [size + 1];' '[size + 1]'如何越界? –
Cuz元素从0开始索引,innit。你知道C++不是Fortran。 – Bathsheba
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
整数。这个数组内的有效索引从0
到size
(而不是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;
此外,你应该delete
的老elements
阵列之前将新创建一个,如:
// 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[]
是昂贵的,最好是最小化它们。 (虽然这种容量优化可能或可能不是你的老师在这个学习过程中想要的。)
谢谢,现在相当清楚!为什么你为新尺寸指定'const'?比只使用'size + 1'更好吗? –
不客气。我很高兴我有一些帮助。我认为用'const'定义一个只读变量(即一个你不能修改的变量)并在其中存储新的大小值,使得代码更清晰并且比在几个地方重复“size + 1”更少的bug发生并且可能在某处丢失了“+1”......无论如何,随意选择你觉得更具可读性的东西。 –
哦,这不是一个性能收益问题吗?他们执行的方式是一样的吗? –
'elements = new int [size + 1];'你在这里失去了我。你为什么要分配**另一个**缓冲区? – StoryTeller
因为我想将临时数组中的所有内容都复制到新元素数组中以实际保留旧值+我们正在推动的新值。 –
'elements_temp [size + 1] = value;'是未定义的行为。 –