-2

这是我的代码:

template<class T> class Test 
{
    public:
    int Size = 0;
    int Length = 0;
T* Items; 

    Test() {}

~Test() 
    {  
    delete [] Items; 
    }

    void Append(const T& newItem) 
{
        if (Size + 1 >= Length)
    {   
        Length += 250;
            T* old = Items; 
        Items = new T[Length + 250]; 
            for (int i = 0; i < Size; i++) 
           Items[i] = old[i];
            delete [] old; 
        }

        Items[Size] = newItem;  
    Size++;
} 
};

Test<int> test;
for (int i = 0; i < 500000; i++)
   test.Append(i);

我正在用 500000 个整数填充动态数组,这些整数必须只占用 1-2Mb,但大约需要 30Mb。如果我将初始大小设置为 500000(即不发生调整大小),则没有问题。增长值(250)似乎会以某种方式影响内存,如果它更大(例如 1000)那么内存使用率非常低。怎么了?

4

2 回答 2

1

查看您的代码,您将比泄漏内存更多地发生段错误,因为调用deletedelete[]在非 NULL 但先前已解除分配的指针是一件坏事。另外,我不相信这是您的真实代码,因为您发布的内容无法编译。

当您delete使用指针时,请始终将其设置为 NULL。初始化为 NULL 也是一个好习惯。让我们修复您的代码,以确保我们不会调用delete以前释放的指针。另外,让我们将指针初始化为 NULL。

您对内存的滥用可能源于以下代码行:

Length += 250;
T* old = Items; 
Items = new T[Length + 250];

请注意,您将 Length 增加了 250,但随后又分配了 Length+250 个元素?让我们也解决这个问题。

template<class T> 
class Test 
{
public:
    int Size;
    int Length;
    T* Items; 

    Test() : Size(0), Length(0), Items(NULL){}

    ~Test() {
       if (Items != NULL)
          delete [] Items; 
    }

    void Append(const T& newItem) 
    {
        if (Size + 1 >= Length)
        {   
           Length += 250;
           T* old = Items; 
           Items = new T[Length]; 
           for (int i = 0; i < Size; i++) 
              Items[i] = old[i];
           delete [] old;
           old = NULL;
        }

        Items[Size] = newItem;  
        Size++;
    } 
};

int main(){
    Test<int> test;
    for (int i = 0; i < 500000; i++)
       test.Append(i);
}
于 2013-10-30T17:02:36.043 回答
1

通常,当您重新分配数组时,您不希望在最后一秒之前修改实际数组(以保持异常安全):

T* temp = new T[new_size]; 
// assume count is the previous size and count < new_size
std::copy(Items, Items + count, temp);
std::swap(temp, Items);
delete [] temp;

除此之外,您的代码中没有任何可见的东西会导致内存泄漏。

额外的大小可能是由于其他优化(被关闭)和/或调试符号被打开。您正在使用哪些编译器选项(以及什么编译器)?应该注意的是,额外的大小不一定表示内存泄漏。您是否在发现泄漏的调试器或内存分析器中运行它?

还应该注意的是,std::vector它会为您完成所有这些工作。

于 2013-10-29T19:04:58.083 回答