C++对象计数

对象计数是C++中一种常见的技术,在-x引擎中也封装了很多对象计数的方法,这里是查阅了相关资料后对常见的对象计数方法进行总结。

一个比较简单的单类的计数就是:

class Sprite
{
public:
    Sprite() { m_count++; };
    ~Sprite() { m_count--; };

    int getCount() { return m_count; };

private:
    static int m_count;
};

int Sprite::m_count = 0;

static类型的成员变量保证了所有对象的共享,如果Sprite是派生自一个基类的话,基类的析构函数一定要是虚函数,原因有很多,之前的文章也说过,基类的析构函数为虚函数可以保证如果使用基类的指针指向派生类对象,但用基类的指针删除对象的时候可以保证不会出现资源泄漏。这里的原因是保证对象计数的正常。

class Node
{};

class Sprite : public Node
...
Node* ptr = new Sprite;
delete ptr;

这个时候如果Node的析构函数不是虚函数,delete调用的Node的析构函数,Sprite的计数值就会出现问题。当然从封装的思想来看,如果对每个类都这样进行操作肯定是不行的,所以我们可以用模板(模板类的封装保证了不同类的计数的独立)来统一进行封装。

template <class T>
class ObjectCounter
{
public:
    ObjectCounter() { m_count++; };
    ~ObjectCounter() { m_count--; };

    int getObjectCounter() { return m_count; };

private:
    static int m_count;
};

template <class T>
int ObjectCounter<T>::m_count = 0;

class Sprite : public Node
{
public:

private:
    ObjectCounter<Sprite> m_counter;
};

这里就来做一道应用题,假设我是一名暴雪的程序员,来为魔兽争霸设计程序表示暗夜精灵的单位,这个时候我们试着按照上面的方法。

class NightElfUnit
{
};

class Archers : public NightElfUnit
{
    ObjectCounter<Archers> m_counter;
};

class Huntress : public NightElfUnit
{
    ObjectCounter<Huntress> m_counter;
};

class Deer : public NightElfUnit
{
    ObjectCounter<Deer> m_counter;
};

这个时候我们可能已经看到自己的错误了,魔兽的人口是共享的,而我们计数是共享的,如果加到基类里面,魔兽不同兵种占用的人口是不同的,这个时候应该怎么办呢?可以修改我们的Counter类。

template <class T>
class ObjectCounter
{
public:
    ObjectCounter(int step = 1)
    {
        m_step = step;
        m_count += m_step;
    };
    ~ObjectCounter()
    {
        m_count -= m_step;
    };

    int getObjectCounter() { return m_count; };

private:
    static int m_count;
    int m_step;
};

这样在Archers,Huntress等单位中将成员变量初始化为ObjectCounter类型,共享统一的计数器,初始化的时候指定占用人口即可。

当然C++对象计数的方法很多,抽空再去抓下-x3.0的代码,看看内部的计数方法的实现。

时间: 2024-10-11 17:32:40

C++对象计数的相关文章

大数据计算:如何仅用1.5KB内存为十亿对象计数

在Clearspring,我们从事统计数据.统计一组不同元素且数量很大的数据集时,是一个挑战. 为了更好地理解已经明确基数的大数据集的挑战,我们假设你的日志文件包含16个字符的ID,并且你想统计不同ID的数量.例如: 4f67bfc603106cb2 这16个字符需要用128位来表示.6万5千个ID将需要1MB的空间.我们每天收到30多亿条事件记录,每条记录都有一个ID.这些ID需要3840亿位或45GB的存储.而这仅仅是ID字段需要的空间.我们采取一种简单的方法获取日常事件记录中以ID为基数的

Problem E: 时间类的静态成员计数

Description 封装一个时间类Time,用于时间处理的相关功能,支持以下操作: 1. Time::Time()无参构造方法. 2. Time::Time(int,int,int)构造方法:传递时分秒的三个参数构造对象. 3. Time::Time(const T&)拷贝构造方法. 4. 对象整体读写方法: Time::setTime(int,int,int)方法:传递时分秒三个参数修改Time对象的时分秒数.该方法返回修改后的对象. Time::setTime(const T&)方

Windows内核之内核对象

1内核对象定义: 1.1:每个内 核对象只是内核分配的一个内存块,并且只能由该内核访问. 1.2:该内存块是一种数据结构,它的成员负责维护该对象的各种信息. 有些数据成员(如安全性描述符.使用计数等)在所有对象类型中是相同的,但大多数数据成员属于特定的对象类型.例如,进程对象有一个进程ID .一个基 本优先级和一个退出代码,而文件对象则拥有一个字节位移.一个共享模式和一个打开模式. 2内核对象种类: 比如存取符号对象. 事件对象.文件对象.文件映射对象.I / O 完成端口对象.作业对象.信箱对

.NET对象与Windows句柄(二):句柄分类和.NET句柄泄露的例子

上一篇文章介绍了句柄的基本概念,也描述了C#中创建文件句柄的过程.我们已经知道句柄代表Windows内部对象,文件对象就是其中一种,但显然系统中还有更多其它类型的对象.本文将简单介绍Windows对象的分类. 句柄可以代表的Windows对象分为三类,内核对象(Kernel Object).用户对象(GDI Object)和GDI对象,上一篇文章中任务管理器中的“句柄数”.“用户对象”和“GDI对象”计数就是与这几类对象对应的.为什么要这样分类呢?原因就在于这几类对象对于操作系统而言有不同的作用

ASP.NET内置对象二

(1)Respose对象 利用Response对象输出文字信息: protected void Page_Load(object sender, EventArgs e){ string message = "您好,欢迎光临本网站!"; Response.Write(message); } 利用Response对象实现网页跳转: protected void Page_Load(object sender, EventArgs e) { Response.Redirect("

.net开发Ae释放com对象的问题

本文转载自: http://www.cnblogs.com/yhlx125/archive/2011/11/22/2258543.html#2269154我的博文 http://www.cnblogs.com/tendzzss/archive/2011/11/11/2245627.html ae的com对象是需要释放的,不然就可能会锁住一些基础设备(如mdb文件等),这里研究了一下ae锁mdb的情况. 释放方法一般是,Marshal.ReleaseComObject或Marshal.FinalR

跨进程边界共享内核对象

正在拜读<windows核心编程>,稍后总结.---------XiaoF 先说说为何要实现此功能   1,利用文件映射对象,可以在同一电脑的不同进程之间共享数据块.   2,借助邮件槽和命名管道,在网络中的不同计算机上运行的进程相互发送消息.   3,互斥量.信号量.事件,允许不同进程中的线程做同步.如何实现,方法3种:使用对象句柄继承(父子进程):为对象命名:复制对象句柄.使用对象句柄继承    只有在父子进程关系,才可以用对象句柄继承方法.    步骤如下:    1,当父进程创建一个内

内存管理 ---slab机制 分配对象

从一个缓存中分配对象总是遵循下面的原则: 1.本地高速缓存中是否有空闲对象,如果有的话则从其中获取对象, 2.如果本地高速缓存中没有对象,则从kmem_list3中的slab链表中寻找空闲对象并填充到本地高速缓存再分配: 3.如果所有的slab中都没有空闲对象了,那么就要创建新的slab,再分配 . 来自:http://blog.csdn.net/vanbreaker/article/details/7671211 Linux内核从slab中分配内存空间由kmalloc()或kmem_cache

C++中临时对象的学习笔记

http://www.cppblog.com/besterChen/category/9573.html 所属分类: C/C++/STL/boost 在函数调用的时候,无论是参数为对象还是返回一个对象,都将产生一个临时对象.这个笔记就是为了学习这个临时对象的产生过程而写. 本代码的详细例子见实例代码Ex.01 Ok,先让我们定义一个类: class CExample { public: int m_nFirstNum; int m_nSecNum; int GetSum(); bool SetN