我正在学习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.
为什么会发生这种情况,为什么只会发生有时?
P.S。:我实际上是否必须释放elements_temp
或者在函数存在后它是否已被释放?
答案 0 :(得分:5)
当您访问数组边界外的元素时,elements_temp[size + 1] = value;
的行为未定义。
这种未定义的行为表现为偶尔的程序崩溃。
是的,您需要在delete[]
返回的指针上明确地调用new[]
。 (出于兴趣,谁在delete[]
上致电elements
?)
或者,使用std::vector<int>
。
答案 1 :(得分: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
个整数。此数组中的有效索引从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;
更好的分配政策
我想补充一点,每次向其中添加项目时分配 new 数组都是一种非常低效的策略。更好的方法(例如由标准std::vector
容器使用)是预先分配一些内存 ,创建一种可用的容量,然后分配一个< em> new 数组并将旧数据复制到新数组,仅当旧向量没有空间时(换句话说,只有当没有更多“容量”可用时)。
事实上,new[]
的动态内存分配很昂贵,最好将它们最小化。 (虽然在此学习过程中,这种能力优化可能是您的老师想要的,也可能不是。)