创建动态分配的数组

时间:2013-10-25 07:41:39

标签: c++

我正在尝试创建一个动态分配的数组,当填充时,会创建一个足够大的新数组来保存所有内容,并将旧数组中的所有值复制到新数组中。我在我的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;
    }
}

5 个答案:

答案 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)

您正在使用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. e中插入append后,无需重新分配,您只需等待就此无法执行此操作。
  4. 使用append的分摊常量复杂度更有效