我正在尝试创建一个动态分配的数组,当填充时,会创建一个足够大的新数组来保存所有内容,并将旧数组中的所有值复制到新数组中。我在我的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 :(得分:2)
问题在于:
for (i=0; i<(size+origsize); i++) {
tmp[i] = arr[i];
}
arr的长度为“大小”,但您正在尝试访问超出它的元素。它将导致未定义的行为。
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
}
}
答案 1 :(得分:2)
你的arr现在是tmp。我的意思是他们都指向一个新阵列。你需要删除旧的。做
int* old = arr;
arr = tmp;
delete [] old;
arr[last] = value;
答案 2 :(得分:0)
新阵列指向旧阵列。
因此,在您的代码中(无需修改),您无法删除arr
答案 3 :(得分:0)
你肯定应该删除tmp,因为你已经使用*将它声明为指针。离开示波器(离开下一个)后,它不会自动解除分配,并会导致内存泄漏。关于指针的有用帖子here以及如何声明它将它放在堆上并要求手动删除它。 既然你想在这里制作一个动态数组。我想你想要arr成为指针,而不是tmp。 查看this c++ tutoriall
答案 4 :(得分:0)
您正在使用new
和delete
,这是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;
}
它与您的代码有何不同:
size
个元素(你读的越界)std::unique_ptr
。e
中插入append
后,无需重新分配,您只需等待就此无法执行此操作。append
的分摊常量复杂度更有效