new和delete
malloc和new区别
- malloc按字节开辟内存;new开辟内存时需要指定类型new int[10]
所以malloc开辟内存返回的都是void* ,上面的operator new返回的是int*- malloc只负责开辟空间,new不仅仅有malloc的功能,可以进行数据的初始化new int(20);new int20;(20个元素初始化为0)
- malloc开辟内存失败返回nullptr指针;new抛出来的是bad_alloc类型的异常
free和delete区别?
- delete:调用析构函数;再free。
void* operator new(size_t size)
{
void* p = malloc(size);
if(p==nullptr)
{
throw bad_alloc();
}
return p;
}
void operator delete(void* ptr)
{
free(ptr);
}
void* operator new[](size_t size)
{
void *p = malloc(size);
if (p == nullptr)
throw bad_alloc();
return p;
}
void operator delete(void* ptr)
{
free(ptr);
}
int main()
{
try
{
int* p = new int;
delete p;
}
catch(const bad_alloc& err)
{
cerr << err.what() << endl;
}
return 0;
}
new和delete能混用嘛?为什么要区分单个元素和数组的申请和释放?
对于普通的编译器内置类型 new/delete[] new[]/delete 可以混合使用
自定义的类类型,有析构函数,为了调用正确的析构函数,那么开辟对象数组的时候,
会多开辟4个字节,记录对象的个数,不能混合使用!
new T[size]如果用delete,那么就相当于从0x104开始释放,很明显必须从0x100开始释放才是合法的,所有T是自定义类类型的话,直接报错!delete认为只有一个对象,把T[0]析构,然后free,底层内存其实是从0x100开始的!
对象池!
template<typename T>
class Queue
{
public:
Queue()
{
//指向头节点!
_front = _rear = new QueueItem();
}
~Queue()
{
QueueItem* cur = _front;
while(cur != nullptr)
{
_front = _front->_next;
delete cur;
cur = _front;
}
}
void push(const T& val)
{
QueueItem* item = new QueueItem(val);
_rear->_next = item;
_rear = item;
}
void pop()
{
if(empty())
return ;
QueueItm* first = _front->_next;
_front->_next = first->_next;
if(_front->_next == nullptr)
_rear = _front;
delete first;
}
T front() const
{
return _front->_next->_data;
}
private:
struct QueueItem
{
//对象池(10000个QueueItem结点!)
QueueItem(T data=T())
:_data(data),_next(nullptr){}
void* operator new(size_t size)
{
if(_itemPool == nullptr)
{
_itemPool = (QueueItem*)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];
QueueItem* p = _itemPool;
for(;p<_itemPool+POOL_ITEM_SIZE-1;++p)
{
p->_next = p+1;
}
p->_next = nullptr;//最后一个地址域为nullptr
}
QueueItem* p = _itemPool;
_itemPool = _itemPool->_next;
return p;
}
void operator delete(void* ptr)
{
QueueItem* p = (QueueItem*)ptr;
p->_next = _itemPool;
_itemPool = p;
}
T _data;
QueueItem* _next;
//新特性里面static可以在类内初始化!
static const int POOL_ITEM_SIZE=100000;
static QueueItem* _itemPool;
};
QueueItem* _front;//指向头节点
QueueItem* _rear;//指向队尾
}:
//类外初始化!
template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::itemPool = nullptr;
那么对象池用完了,咋办?
不影响,到池子最后一个对象时,_next域为空,new的时候判断到为空,那么继续申请池子!