`

C++11应用:对象池

 
阅读更多

    ObjectPool.hpp:

#pragma once

#include <string>
#include <memory>
#include <functional>
#include <map>

using namespace std;

template <typename T>
class ObjectPool
{
	template <typename... Args>
	using Constructor = std::function<std::shared_ptr<T>(Args...)>;
public:
	~ObjectPool()
	{
		destructedFlag = true;
	}

	// 默认创建多少个对象
	template <typename... Args>
	void Init(size_t num, Args&&... args)
	{
		if (num <= 0)
		{
			throw std::logic_error("object num out of range!");
		}
		m_object_map.clear();
		auto constructName = typeid(Constructor<Args...>).name(); // 不区分引用
		for (size_t i = 0; i < num; i++)
		{
			m_object_map.emplace(constructName, std::shared_ptr<T>(new T(std::forward<Args>(args)...), [this, constructName](T* p)
			{
				// (析构函数)删除器中不直接删除对象,而是回收到对象池中,以供下一次使用
				if (!destructedFlag) // 解决内存中释放的时序造成的野指针,如果ObjectPool对象先释放,T对象后释放,则触发这里emplace会卡死
				{
					m_object_map.emplace(std::move(constructName), std::shared_ptr<T>(p));
				}
				else {
					delete p;
				}
			}));
		}
	}
	// 从对象池中获取一个对象
	template <typename... Args>
	std::shared_ptr<T> Get()
	{
		string constructName = typeid(Constructor<Args...>).name();
		auto range = m_object_map.equal_range(constructName);
		for (auto it = range.first; it != range.second; ++it)
		{
			auto ptr = it->second;
			m_object_map.erase(it);
			return ptr;
		}
		return nullptr;
	}

private:
	multimap<string, std::shared_ptr<T>> m_object_map;
	bool destructedFlag = false;

};

    测试代码:

#include <iostream>
#include <string>  

#include "ObjectPool.hpp"
 
using namespace std;

struct MyObj
{
	MyObj() 
	{
		cout << "MyObj construct... 0x" << hex << this << endl;
	}
	MyObj(int a)
	{
		cout << "MyObj construct:" << a << " 0x" << hex << this << endl;
	}
	MyObj(const int& a, const int& b) 
	{
		cout << "MyObj construct a:" << a << " b:" << b << " 0x" << hex << this << endl;
	}
	~MyObj()
	{
		cout << "MyObj destruct... 0x" << hex << this << endl;
	}
	void print(const string& str)
	{
		cout << "print:" << str.c_str() << endl;
	}
};
void printTest(std::shared_ptr<MyObj> p, const string& str)
{
	if (p != nullptr)
	{
		p->print(str);
	}
	else {
		cout << "printTest error: p is nullptr..." << endl;
	}
}

void TestObjPool() 
{
	ObjectPool<MyObj> pool;
	pool.Init(2); // 初始化两个对象

	// 除了下面的作用域,对象又会自动回收
	{
		auto p1 = pool.Get();
		printTest(p1, "p1...");

		auto p2 = pool.Get();
		printTest(p2, "p2...");
		cout << "---------------------" << endl;
	}

	auto p1 = pool.Get();
	auto p2 = pool.Get();
	printTest(p1, "p1");
	printTest(p2, "p2");
	cout << "===========================0" << endl;

	ObjectPool<MyObj> pool2;
	pool2.Init(2, 1); // 初始化两个对象,并用1来实例对应的对象构造函数
	auto p4 = pool2.Get<int>();
	printTest(p4, "p4");
	cout << "===========================1" << endl;

	pool.Init(2, 3, 4); // 初始化两个对象,并用3和4来实例对应的对象构造函数
	auto p5 = pool.Get<int, int>();
	printTest(p5, "p5");
	cout << "===========================2" << endl;
}

int main(int, char *[])
{     
	
	TestObjPool(); 

	system("pause");
	return 0;
}

    虽然同一个ObjectPool可以执行多次Init,但所有Init创建的实例,都要在该ObjectPool释放时,才能被释放。 

 

 

 

分享到:
评论

相关推荐

    MemoryPool:使用 C++11 的简单内存池实现

    在C++11中,我们可以利用其新引入的特性来实现一个简单的内存池。本项目就是针对这一主题的一个实践,适用于Visual Studio 2015、g++4.8和clang++3.4等编译器。 内存池的基本思想是避免频繁的系统调用,因为传统的...

    C++对象池源码示例

    本篇将深入探讨对象池的概念、工作原理以及如何在C++中实现对象池。 对象池的基本思想是预先创建并维护一组对象,而不是每当需要时就动态地创建新对象,然后在不再需要时再销毁它们。这种策略可以显著减少对象生命...

    c++实现游戏开发中常用的对象池(含源码)

    本资源提供了一个用C++实现的对象池模型,包括了源码,可以帮助开发者深入理解并应用对象池设计模式。 首先,让我们详细探讨对象池的五要素: 1. **对象集合**:这是对象池的核心部分,它存储了所有可复用的对象。...

    C++高效编程:内存与性能优化

    在C++编程中,内存管理和性能优化是两个关键领域,对于开发高质量、高效能的应用程序至关重要。本主题将深入探讨这两个方面,旨在帮助开发者更好地理解如何编写更优化的C++代码。 内存管理是C++的核心特性之一,...

    深入探索C++内存池:高效内存管理的秘诀

    C++广泛应用于系统软件、应用软件开发、游戏开发、嵌入式系统、高性能服务器和客户端应用程序等领域。 C++的一些关键特性包括: - 面向对象编程:支持类、继承、多态和封装等概念。 - 泛型编程:通过模板支持,允许...

    对象池 射击游戏 子弹的反复生成

    5. **代码注释**:为了帮助理解,Demo案例中的代码会有详细的注释,解释每个步骤的作用和实现方式,帮助开发者更好地理解和应用对象池技术。 通过学习这个Demo,开发者可以了解到如何在实际项目中应用对象池,如何...

    游戏对象池例子(兼容智能指针、工厂类)

    在这个"游戏对象池例子(兼容智能指针、工厂类)"中,我们将探讨如何利用C++实现这种技术,并结合智能指针和工厂模式来确保兼容性和效率。 1. **对象池概念**: 对象池的基本思想是预先创建一批对象,当需要对象时...

    100行C++代码实现线性池

    线性池,也称为对象池或者内存池,是一种内存管理技术,主要应用于程序设计中,尤其是在需要频繁创建和销毁对象的场景下。它的核心思想是预先分配一大块内存,然后根据需要从中分配小块内存,而不是每次都需要向操作...

    C++对象内存池 ---- C++侦探改写.rar

    8. **应用实例**:内存池广泛应用于数据库、网络服务、游戏引擎等领域,这些场景通常涉及到大量小对象的快速创建和销毁。 总的来说,C++对象内存池是一种高效内存管理技术,通过预先分配和统一管理内存,能有效提升...

    C++内存池实现

    内存池是一种优化内存分配策略的技术,它在C++编程中被广泛应用,特别是在处理大量小对象分配和释放时,能够显著提升程序性能。本项目提供的是一个自定义实现的C++内存池,包括文档和源代码,旨在帮助理解内存池的...

    每天学点C++(C++实例教程:教程+源码)多线程编程.zip

    通过这个C++实例教程和源码,你可以学习到如何在实际项目中应用这些概念,理解多线程编程的挑战和优势,以及如何编写高效的多线程代码。记得实践是检验真理的唯一标准,动手尝试这些示例,将有助于你更好地掌握C++的...

    c++高性能内存池.rar

    std::allocator 是 C++标准库中提供的默认分配器,他的特点就在于我们在 使用 new 来申请内存构造新对象的时候,势必要调用类对象的默认构造函数 而使用 std::allocator 则可以将内存分配和对象的构造这两部分...

    mongodb的c++连接接口

    7. **性能优化**:C++ 驱动允许进行一些性能优化,比如批量操作、连接池管理、异步操作等,这有助于提高应用程序的整体性能。 8. **安全注意事项**:在实际应用中,确保正确处理用户输入,防止 SQL 注入攻击,并且...

    C++面向对象程序设计 游泳池

    在这个“C++面向对象程序设计 游泳池”实验中,我们将探讨如何利用C++的OOP特性来构建一个模拟游泳池的类结构。 首先,我们需要定义“游泳池”这个类。类是OOP中的核心构造块,它封装了数据(成员变量)和行为...

    几种内存池的实现(c/c++ 源码)

    在C/C++编程中,内存池常用于频繁创建和销毁小对象的场景,如网络编程、数据库连接等。本文将深入探讨几种内存池的实现方式及其源码分析。 1. **静态内存池**: 静态内存池在程序启动时就分配好内存,且在程序运行...

    Visual C++ 实践与提高:COM和COM+篇 PDF文件

    COM+事件系统使得组件间的异步通信更加简单,对象池提高了组件创建和销毁的效率,自动事务处理确保了操作的原子性,线程模型则提供了多种多线程处理策略以适应不同的应用场景。 此外,COM+还引入了服务组件...

    linux C/C++ 数据库连接池

    在Linux环境下,C/C++开发数据库连接池是提高应用程序性能和效率的重要技术。数据库连接池是一种管理数据库连接的机制,它允许程序重复使用已建立的数据库连接,而不是每次需要时都创建新的连接。这减少了创建和销毁...

    C++内存池的管理

    在IT行业中,内存管理是程序设计中的重要环节,尤其是在C++这种低级语言中,对内存的精细控制能显著提高程序的...深入理解并合理应用内存池,能够提升C++程序的性能和稳定性,是每个C++程序员应该掌握的高级技巧之一。

    C++内存池完整代码memory_pool.zip

    内存池是一种优化内存分配策略的技术,它在C++编程中被广泛应用,特别是在处理大量小对象分配和释放时,能够显著提高性能并减少内存碎片。内存池的基本思想是预先分配一大块连续的内存,并通过自己的管理机制来分配...

    c++ 面向对象多线程编程

    总之,C++的面向对象特性和多线程支持使得开发者能够构建复杂、高效的应用程序。通过熟练掌握这些概念和实践,你将在软件开发领域更上一层楼。在实际项目中,要始终考虑线程安全、性能优化以及代码的可读性和可维护...

Global site tag (gtag.js) - Google Analytics