C++|深入了解C++的new和delete

new 和delete 运算符
malloc 和 new 的区别?
1、malloc按字节开辟内存的;new开辟内存时需要指定类型 new int[10],所以malloc开辟内存返回的都是void*
2、malloc只负责开辟空间 new不仅有malloc的功能,还可以进行数据的初始化
new int(20)
3、malloc开辟内存失败返回nullptr指针,new开辟失败抛出bad_alloc类型的异常

free和delete的区别?
delete:调用析构函数,再free
new和delete是调用new运算符重载函数

如何判断是否存在内存泄漏?
哪些new没有对应的delete,自定义new和delete的重载函数,接管内存的开辟和释放,并做记录(内存映射)

new和delete能混用吗 ,C++为什么区分单个元素和数组的内存分配和释放呢?
new和delete
new[] 和delete[]
对于普通的编译器内置类型 可以混用
自定义的类类型,有析构函数,为了调用正确的析构函数,开辟对象数组的时候,会多开辟4个字节,记录对象的个数

自定义new和delete的运算符重载函数:

//先调用operator new开辟内存空间、再调用对象的构造函数
void * operator new(size_t size)
{
	void *p = malloc(size);
	if (p == nullptr)
	{
		throw bad_alloc();
	}
	return p;
}
//调用p指向对象的析构函数、再调用operator delete释放内存空间
void operator delete(void *p)
{
	free(p);
}
int main()
{
	//内置类型可以混用
	int *p = new int();
	delete []p;

	//类类型 不可混用
	test *ptr = new test();
	delete[]ptr;//编译器当做数组类型处理,会去寻找存放数据个数的内存空间,但并没有,并且在释放内存时,会从ptr-4位置开始

	return 0;
}

实现一个对象池

//队列

#include 
using namespace std;

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 ;
		delete _front;
		QueueItem *first=_front->_next;
		_front->_next = first->_next;
		if (_front->_next == nullptr)
		{
			_rear = _front;
		}
		delete first;
	}
	T front()const
	{
		return _front->_next->data;
	}
	bool empty()const { return _front == _rear; }
private:
	struct QueueItem
	{
		QueueItem(T data=T()):_data(data),_next(nullptr){}
		//给QueueItem提供自定义的内存管理
		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;
			}
			QueueItem *p = _itempool;
			_itempool = _itempool->_next;
			return p;
		}

		void operator delete(void * ptr)
		{
			QueueItem *p = (QueueItem *)ptr;
			p->_next = _itempool;
			_itempool = p;
		}
		static const int POOL_ITEM_SIZE = 10000;
		static QueueItem *_itempool;
		
		T _data;
		QueueItem *_next;
	};
	QueueItem *_front;
	QueueItem *_rear;

};

template<typename T>
typename Queue<T>::QueueItem  *Queue<T>::QueueItem :: _itempool = nullptr;

int main()
 {
	Queue<int> que;
	for (int i = 0; i < 1000000; ++i)
	{
		que.push(i);
		que.pop();
	}
	return 0;
}

//1000000是一个很庞大的数据,不断调用push和pop的过程中
//也不断使用了new和delete 不断malloc和free,浪费时间
//所以思考产生一个QueueItem的对象池

你可能感兴趣的:(C++|深入了解C++的new和delete)