14. 对象池newnew[ ]deletedelete[ ]混用

Posted 为了财务自由!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了14. 对象池newnew[ ]deletedelete[ ]混用相关的知识,希望对你有一定的参考价值。

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

以上是关于14. 对象池newnew[ ]deletedelete[ ]混用的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C 自动释放池不释放对象

如何在计时器上更改python customedraw文本?怎么样?

在Rust中设置对象参数的性能[关闭]

JAVA基础知识总结14(StringStringBufferStringBuilder)

14DBCP连接池

14.UA池和代理池