14. 对象池、new、new[ ]、delete、delete[ ]混用

new和delete
malloc和new区别

  1. malloc按字节开辟内存;new开辟内存时需要指定类型new int[10]
    所以malloc开辟内存返回的都是void* ,上面的operator new返回的是int*
  2. malloc只负责开辟空间,new不仅仅有malloc的功能,可以进行数据的初始化new int(20);new int20;(20个元素初始化为0)
  3. malloc开辟内存失败返回nullptr指针;new抛出来的是bad_alloc类型的异常

free和delete区别?

  1. 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的时候判断到为空,那么继续申请池子!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值