C++基础之创建对象和对象计数

来源:互联网 发布:百度网盘mac版是什么 编辑:程序博客网 时间:2024/05/12 16:16

【创建C++对象】

当创建一个C++对象时,会发生2件事情:

1. 为对象分配内存

1) 在静态存储区分配,存储空间在程序开始之前就分配好了,这块内存在程序的整个运行期间都在。静态存储区主要保存全局变量,静态变量,常量。

2) 在栈上。写程序的时候,必须知道需要多少个存储单元,生命周期是距离最近的一对大括号{ },自动调用构造函数和析构函数。使用 '.' 点运算符来引用成员。

3) 在堆上。这是动态内存分配的方式,由程序员来决定分配多少内存,以及何时释放内存。使用 -> 运算符来引用成员。

int size = 5;//int mem[size]; //Must have a constant valueint* mem = new int[size];

2. 调用构造函数来初始化这块内存

 

下面重点说说2)和3)两种创建对象的方法。类Rec有2个int型成员变量。

class Rec{public:Rec(int width, int height){m_width = width;m_height = height;}~Rec(){};int GetArea(){return m_width * m_height;};private:int m_width;int m_height;};

用两种创建方法分别创建2个Rec对象。

Rec r(2, 5);Rec* pr = new Rec(2,5);cout << sizeof(r) << endl;   //Output: 8cout << sizeof(pr) << endl;  //Output: 4cout << sizeof(*pr) << endl; //Output: 8

对象 r 直接在栈上创建,大小是8。

pr是一个指向Rec对象的指针,这里发生了3件事情。

1))new 在堆上为对象分配内存(大小为8),并为这块内存调用构造函数。

2)在栈上分配一个Rec的指针pr。

3)将pr指向堆上的内存。

【对象计数】

在有些场合,需要知道某个类有多少个对象。最简单的做法,是在类里面增加一个静态变量用于计数,分别在构造函数和析构函数中,对计数进行增减。

class Widget{public:Widget(){m_count++;}Widget(const Widget&){m_count++;}~Widget(){m_count--;}static int GetCount(){return m_count;}private:static int m_count;};int Widget::m_count = 0;

 

但是这种方法不通用,如果有多个类需要进行对象计数,难道要在每个类中增加这么一套东西吗?最好是实现一个通用的计数类。

template<class T>class Counter{public:Counter(){m_count++;}Counter(const Counter&){m_count++;}~Counter(){m_count--;}static int GetCount(){return m_count;}private:static int m_count;};


这个通用的计数类使用了模板。因为Counter的静态成员m_counter是被使用Counter的类(客户类)的所有成员共享的,如果有两个类Apple和Banana都包含了

Counter m_MyCounter;

那么其实Apple和Banana实际上是在共享同一个计数值。使用模板以后,Counter<Apple> 和 Counter<Banana> 是两个类了,各自的m_MyCounter独立。

有三种方式来使用通用计数类:

1. Counter作为客户类的成员变量。此时Counter的析构函数必须为public。缺点是客户类必须定义Counter为其成员变量,并定义一个inline函数GetCount,增大了客户类占用的内存(虽然Counter类没有非静态变量,但是C++规定所有对象大小最小为1个字节)。

class Widget1{public:static int GetCount(){return Counter<Widget1>::GetCount();}private:Counter<Widget1> m_Counter;};

 

Widget1 w1;Widget1 w2;Widget1 w3;Widget1* pw4 = new Widget1();Widget1* pw5 = new Widget1();cout << w1.GetCount() << endl; //Output: 5cout << pw5->GetCount() << endl; //Output: 5


2. Public继承。基类Counter的析构函数要变成虚函数,这样的话,类会增加虚表的空间。解决方法是将析构函数作为protected成员,这样就不能delete pw了(Counter<Widget>* pw = new Widget;),会导致编译错误(??)。

class Widget2: public Counter<Widget2>{};


3. Private继承。似有继承不允许Counter<Widget>* pw = new Widget; 这样的转换,防止了这样的代码出现。

class Widget3: private Counter<Widget3>{//make GetCount() publicusing Counter<Widget3>::GetCount;};

 

个人偏向于第一个方法。

【参考】

Solmyr 的小品文系列之三:对象计数(上)
Solmyr 的小品文系列之四:对象计数(下)

http://tech.163.com/04/1109/16/14OR79770009rt.html

原创粉丝点击