这是我的代码:
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)则内存使用率相当低。怎么了?
答案 0 :(得分: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
为你完成所有这些。
答案 1 :(得分:1)
查看你的代码,你会比泄漏内存更容易发生段错误,因为在非NULL上调用delete
或delete[]
,但之前已解除分配的指针是坏的事情。另外,我不相信这是你真正的代码,因为你发布的内容不会编译。
当你delete
指针时,总是将其设置为NULL。初始化为NULL也是一种很好的做法。让我们修复你的代码,以确保我们不会在先前释放的指针上调用delete
。另外,让我们将指针初始化为NULL。
您对内存的滥用可能源于以下几行代码:
Length += 250;
T* old = Items;
Items = new T[Length + 250];
请注意,您将Length增加250,然后再分配长度+ 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);
}