2013-10-25 38 views
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; 
    } 
} 
+0

只要确保你删除在正确的地方。您的评论会删除'tmp',但我认为您应该在'arr = tmp'行之前删除'arr'。 – Sjlver

+0

......我认为这是学术性的,因此把整个事情抛出来用于'std :: vector '是不可能的。 – WhozCraig

回答

2

的问题是在这里:

for (i=0; i<(size+origsize); i++) { 

     tmp[i] = arr[i]; 

    } 

改编的长度是“大小”,但您要访问的元素超越它。它会导致未定义的行为。

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 
    } 
} 
+0

是的,我宁愿使用我相信的(我们没有在课堂上学过),但是我们的教授特别想要我们......这样做是为了我们自己,我想教我们一些教训,不明白。他不喜欢我们使用我们没有创建的任何函数ourselvs – FrostyStraw

+0

我认为他正在试图实现ArrayList,它只是使用数组并调整它们的大小。 –

2

你的编曲是TMP。我的意思是他们都指向一个新的阵列。你需要删除旧的。做

int* old = arr; 
arr = tmp; 
delete [] old; 
arr[last] = value; 
+0

如果我正确读取它。当您删除arr时,您将删除旧数组。然后你问tmp指出什么arr指向..这是什么,因为arr被删除... – FrostyStraw

+0

我的坏。编辑。 –

+0

所以,如果我只是删除旧的,我只是删除名为旧的指针。但是要删除旧指向的实际数组,我需要删除[]旧的? – FrostyStraw

0

新阵列指向旧的。

因此,在你的代码(withou修改),你不能删除ARR

0

你一定要删除tmp目录,因为,因为你已经使用它声明为一个指针*。一旦离开作用域(离开下一个),它将不会自动释放,并且会导致内存泄漏。关于指针的有用信息here以及如何声明它将其放在堆上并要求手动删除它。 由于您正在尝试在此创建动态数组。我想你想让arr成为指针,而不是tmp。 结账this c++ tutoriall

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. append中插入e之后没有必要重新分配,您可以等待已经用完的地方。
  4. 采用分期常量复杂性append更高效