深入理解C++中的new和delete并实现对象池
1. C++中的new和delete
1.1 new操作符
new操作符是C++中用于动态分配内存的关键字,它可以在堆上分配空间,并返回指向新分配空间的指针。new操作符有多种语法,其中最常用的是:
Type *pointer = new Type;
其中Type表示要分配的类型,pointer是指向新分配空间的指针。例如,下面的代码可以动态分配一个int类型的变量并初始化为1:
int *p = new int(1);
如果要分配一个数组,则可以使用以下语法:
Type * pointer = new Type[length];
其中length表示数组的长度,pointer是指向新分配空间的指针。例如,下面的代码可以动态分配一个长度为10的int类型数组:
int *p = new int[10];
1.2 delete操作符
delete操作符是C++中用于释放内存的关键字,它可以释放new操作符分配的空间并使指针指向的内存变为未定义值。delete操作符也有多种语法,其中最常用的是:
delete pointer;
其中pointer是new操作符返回的指针。例如,下面的代码释放了前面的动态分配的int类型变量:
int *p = new int(1);
delete p;
如果new操作符分配的是数组,则在释放空间时需要使用以下语法:
delete[] pointer;
例如,下面的代码释放了前面动态分配的int类型数组:
int *p = new int[10];
delete[] p;
2. 对象池
2.1 什么是对象池
对象池是一种提高内存利用率的方式,它是一种可重用对象集合,可以在程序启动时预分配一定数量的对象,当需要使用对象时从对象池中获取对象,使用完毕后归还到对象池中,而不是反复使用new操作符分配空间。
2.2 实现对象池
下面给出一个简单的对象池的实现,以std::vector为例:
#include <vector>
#include <iostream>
template<typename T, size_t pool_size>
class ObjectPool
{
public:
ObjectPool()
{
_pool.reserve(pool_size);
for (size_t i = 0; i < pool_size; ++i)
{
_pool.emplace_back(new T);
}
std::cout << "ObjectPool constructor." << std::endl;
}
~ObjectPool()
{
for (auto &obj : _pool)
{
delete obj;
}
std::cout << "ObjectPool destructor." << std::endl;
}
T* Get()
{
if (_pool.empty())
{
return nullptr;
}
auto obj = _pool.back();
_pool.pop_back();
return obj;
}
void Release(T* obj)
{
if (obj != nullptr)
{
_pool.push_back(obj);
}
}
private:
std::vector<T*> _pool;
};
这个对象池使用了一个std::vector来存储对象,其中pool_size表示对象池大小。在对象池的构造函数中,我们使用了std::vector的reserve函数预留了足够的空间,并使用了for循环为对象池中的每个元素初始化。在对象池的析构函数中,我们使用了for循环释放对象池中的每个元素。
在对象池中,我们使用了Get函数获取对象,如果对象池中没有对象可以使用,则返回nullptr。Release函数用于将使用完毕的对象归还到对象池中。
2.3 示例说明
下面给出两个示例说明对象池的使用方式。
首先是使用对象池的方式:
#include "ObjectPool.h"
class Test
{
public:
Test()
{
std::cout << "Test constructor." << std::endl;
}
~Test()
{
std::cout << "Test destructor." << std::endl;
}
void SayHello()
{
std::cout << "Hello, World!" << std::endl;
}
};
int main(int argc, char** argv)
{
ObjectPool<Test, 10> pool;
for (int i = 0; i < 5; ++i)
{
auto p = pool.Get();
if (p != nullptr)
{
p->SayHello();
pool.Release(p);
}
}
return 0;
}
这个示例中,我们首先使用ObjectPool
接下来是不使用对象池的方式:
class Test
{
public:
Test()
{
std::cout << "Test constructor." << std::endl;
}
~Test()
{
std::cout << "Test destructor." << std::endl;
}
void SayHello()
{
std::cout << "Hello, World!" << std::endl;
}
};
int main(int argc, char** argv)
{
for (int i = 0; i < 5; ++i)
{
auto p = new Test;
p->SayHello();
delete p;
}
return 0;
}
这个示例中,我们循环5次调用new操作符动态分配对象并使用它们,使用完毕后再通过delete操作符释放它们。
可以看到,在使用对象池的方式中,对象的构造和析构函数只调用了一次,而在不使用对象池的方式中,对象的构造和析构函数被反复调用了5次,因此,使用对象池可以减少内存分配和释放的开销,提高程序的性能。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解C++中的new和delete并实现对象池 - Python技术站