A simple and generic Object Pool implementation in C++ using templates.
Built as a learning project to understand memory management and object reuse patterns in C++.
Made by a student learning C++, open to feedback and improvements!
| Created without arguments | Created with arguments |
|---|---|
![]() |
![]() |
Example: Pool managing 100 objects in a simple SFML demo.
- Efficiently reuse objects without constant memory allocation/deallocation.
- Great for games, simulations, or any system where object reuse improves performance.
- Uses
std::vector<std::unique_ptr<Object>>internally, giving:- Stack behavior for quick acquire/release (
push_back,pop_back,back) - Easy iteration with range-based for loops.
- Stack behavior for quick acquire/release (
- Written as a C++ template:
ObjectPool<Object> - Stores inactive objects in a
std::vector<std::unique_ptr<Object>>stack acquire()gives you a reusable objectrelease(std::move(obj))returns the object to the pool- Works with any movable object type (copyable optional). For std::unique_ptr, you must use
std::move()when transferring ownership.
#include "ObjectPool.hpp"
#include <iostream>
#include <string>
struct MyObject {
int id;
MyObject(int id = 0) : id(id) {}
};
int main() {
ObjectPool<MyObject> pool;
//ObjectPool<MyObject> pool{100}; // Preallocate 100 objects
// Acquire an object from the pool
auto obj = pool.acquire();
obj->id = 42;
std::cout << "Using object with id = " << obj->id << "\n";
// Return the object to the pool
pool.release(std::move(obj));
// Re-acquire (reuse) the object
auto reused = pool.acquire();
std::cout << "Reused object with id = " << reused->id << "\n";
// Iterate over all objects in the pool
for (auto& o : pool.getAllObjects()) {
std::cout << o->id << "\n";
}
return 0;
}#include "ObjectPool.hpp"
#include <iostream>
#include <sstream>
#define LOG(x) std::cout << x << "\n"
class Enemy {
private:
float m_health;
float m_shield;
std::string m_ability;
float m_speed;
int m_level;
std::string m_name;
public:
Enemy(float health, float shield, const std::string& ability, float speed = 1.0f, int level = 1, const std::string& name = "Enemy")
: m_health(health), m_shield(shield), m_ability(ability), m_speed(speed), m_level(level), m_name(name) {}
~Enemy() {}
void attack() {
std::cout << m_name << " attacks with " << m_ability << " (Level " << m_level << ")\n";
}
void reset(float health = 100.0f, float shield = 50.0f, const std::string& ability = "Basic Attack", float speed = 1.0f, int level = 1, const std::string& name = "Enemy") {
m_health = health;
m_shield = shield;
m_ability = ability;
m_speed = speed;
m_level = level;
m_name = name;
LOG(m_name << " has been reset.");
}
std::string toJSON() const {
std::ostringstream oss;
oss << "{\n"
<< "\t\"name\":\"" << m_name << "\",\n"
<< "\t\"health\":" << m_health << ",\n"
<< "\t\"shield\":" << m_shield << ",\n"
<< "\t\"ability\":\"" << m_ability << "\",\n"
<< "\t\"speed\":" << m_speed << ",\n"
<< "\t\"level\":" << m_level << "\n"
<< "}";
return oss.str();
}
};
int main() {
ObjectPool<Enemy, float, float, const std::string&> enemyPool(10, 100.f, 50.f, "Fire Punch");
auto enemy = enemyPool.acquire();
enemy->attack();
LOG(enemy->toJSON());
enemyPool.release(std::move(enemy));
return 0;
}The pool is implemented as:
std::vector<std::unique_ptr<Object>> pool;Objects are managed in a stack-like manner:
acquire()retrieves the object atback()and removes it from the pool (pop_back()).release(std::move(obj))returns an object to the pool usingpush_back(std::move(obj)).
When the pool is empty, acquire() will construct a new object. If the pool was initialized with constructor arguments, these are perfectly forwarded using std::forward; otherwise, objects are default-constructed.
A Makefile is included to simplify compiling the project(demo).
- Works on Unix/Linux/macOS
- Compatible with Windows (NT) using environments like:
make runThis will compile the project using g++ with C++17.
You can customize the Makefile as needed for your system or compiler.
The core object pool (include/ObjectPool.hpp) is header-only and has no external dependencies.
The demo (demo/ folder) requires:
- SFML (installed via MSYS2 recommended)
On MSYS2 (64-bit MinGW):
pacman -S mingw-w64-x86_64-sfml- Add support for custom object initialization
- Add thread-safety (maybe with mutex?)
- Benchmark vs. dynamic allocation
- Write unit tests
This is a self-learning project. Thanks to tutorials, forums, and anyone sharing C++ knowledge online.
This project is licensed under the MIT License.
If you learn something from this, that's awesome!

