1

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

5 回答 5

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
    }
}
于 2013-10-25T07:46:01.163 回答
2

你的 arr 现在是 tmp。我的意思是它们都指向一个新数组。你需要删除旧的。做

int* old = arr;
arr = tmp;
delete [] old;
arr[last] = value;
于 2013-10-25T07:46:26.847 回答
0

您正在使用newand 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;
}

它与您的代码有何不同:

  1. 当从一个数组复制到另一个数组时,我只复制size元素(你读的越界)
  2. 我不手动处理内存,而是将内存处理推迟到std::unique_ptr.
  3. e插入后无需重新分配append,您只需等待用完即可。
  4. 使用摊销常数复杂度append更有效
于 2013-10-25T08:29:04.417 回答
0

新数组指向旧数组。

所以在你的代码中(没有修改)你不能删除 arr

于 2013-10-25T07:48:42.107 回答
0

您绝对应该删除 tmp,因为您已经使用 *. 一旦离开作用域(离开下一个}),它就不会被自动释放,并且会导致内存泄漏。有用的帖子在这里关于指针以及如何声明它把它放在堆上并要求它被手动删除。由于您试图在这里创建一个动态数组。我认为您希望 arr 成为指针,而不是 tmp。看看这个 c++ 教程

于 2013-10-25T08:01:13.087 回答