New与Delete
New不加括号的差别
1>空类的话无区别。
2>有成员变量,带括号的会把一些和成员变量有关的内存清零,并不是整个对象的内存为零
3>当有构造函数的时候,两种写法一致,不会把内存清零了。由构造函数负责了。
class Test3d
{
public:
Test3d()
{
cout << "Init" << endl;
}
~Test3d()
{
cout << "Delete" << endl;
}
};
int main()
{
Test3d* ptr = new Test3d;
Test3d* ptr2 = new Test3d;
delete ptr;
delete ptr2;
ptr = nullptr;
ptr2 = nullptr;
return 0;
}
New和Delete的运行过程
new
调用了Operate new
调用了Malloc 分配内存
调用了类的构造函数(如果有的话)
delete
调用了类的析构函数
调用了operate delete
调用了Free释放内存
Delete内存的回收,影响范围很广
class Test3d
{
public:
void fun()
{
char* pp = new char[10];
memset(pp, 0, 10);
delete[] pp;
}
};
回收的字节要超过10个字节,可能会更多
分配的内存也不仅仅是分配10个字节,debug模式下调试信息占有30-60字节,记录分配多少,4个字节等等其他操作
operator new 和 operator delete
//自己实现new和delete
class Test3d
{
public:
static void* operator new(size_t size);
static void operator delete(void *phead);
};
void* Test3d::operator new(size_t size)
{
Test3d* ppoint = (Test3d*)malloc(size);
return ppoint;
}
void Test3d::operator delete(void* phead)
{
free(phead);
}
void func()
{
Test3d* pa = new Test3d();
delete pa;
}
int main()
{
func();
return 0;
}
此处的构造函数和析构函数仍然是编译器帮忙处理
如果自己不想用自己写的
Test3d* pa = ::new Test3d();
::delete pa;
前加双冒号,调用系统的new delete
operator new【】 和 operator delete【】
构造和析构会被调用3次,但是operator new 和delete 仅仅调用一次
class Test3d
{
public:
static void* operator new[](size_t size);
static void operator delete[](void *phead);
};
void* Test3d::operator new[](size_t size)
{
Test3d* ppoint = (Test3d*)malloc(size);
return ppoint;
}
void Test3d::operator delete[](void* phead)
{
free(phead);
}
void func()
{
Test3d* ptr = new Test3d[3];
delete[] ptr;
}
int main()
{
func();
return 0;
}
内存池
作用和原理
作用:减少malloc调用次数,减少内存浪费
原理:先malloc申请一大块内存,分配的时候一点点给,如果不够了,再malloc一大块内存
最简易内存池代码实现
class Test3d
{
public:
static void* operator new(size_t size);
static void operator delete(void *phead);
static int m_iCount;//分配计数统计,new一次统计一次
static int m_iMallocCount; //分配计数统计,Malloc一次统计一次
private:
Test3d* next;
static Test3d* m_FreePos;//内存首地址
static int m_sTrunkCount;//分配多少倍的内存
};
int Test3d::m_iCount = 0;
int Test3d::m_iMallocCount = 0;
Test3d* Test3d::m_FreePos = nullptr;
int Test3d::m_sTrunkCount = 5;
void* Test3d::operator new(size_t size)
{
Test3d* tempLink;//需要返回的一个内存块
if (m_FreePos == nullptr)
{
size_t tempSize = m_sTrunkCount * size;
m_FreePos = reinterpret_cast<Test3d*>(new char[tempSize]);
tempLink = m_FreePos;
for (; tempLink!=&m_FreePos[m_sTrunkCount-1]; tempLink++)
{
tempLink->next = tempLink + 1;
}
tempLink->next = nullptr;
++m_iMallocCount;
}
++m_iCount;
tempLink = m_FreePos;
m_FreePos = m_FreePos->next;
return tempLink;
}
void Test3d::operator delete(void* phead)
{
(static_cast<Test3d*>(phead))->next = nullptr;
m_FreePos = static_cast<Test3d*>(phead);
}
void func()
{
clock_t start, end;
start = clock();
for (int i = 0;i<500'0000;i++)
{
Test3d* ptr = new Test3d();
}
end = clock();
cout << "申请分配内存的次数为:" << Test3d::m_iCount << endl;
cout << "实际malloc的次数为:" << Test3d::m_iMallocCount << endl;
cout << "用时为:" << end - start << "毫秒" << endl;
}
int main()
{
func();
return 0;
}
注:此版本为最简易版本,可以观察内存池的具体优化时间表现。