C++之所以难使用除了语法太复杂之外,另一个原因就是内存管理需要程序员自己控制了。也正式因为拷贝构造函数的存在,使得很多时候,不注意就陷入了拷贝构造函数带来的空指针异常。所以尽量避免拷贝构造函数的使用,会使得内存管理更加方便,约定一些规范去使用C++,会使C++更加容易使用。
使用引用计数来管理内存是一种常见的内存回收算法,也是比较容易实现的算法。下面就是一个简单的引用计数内存回收实现。
我创建了一个基类,项目所有的自定义类必须继承该类,并且自定义类的拷贝构造函数必须设置为private。
//// 通过引用计数来完成C++的自动内存回收,这是所有自定义类的基类//#ifndef CLUSTER_CHAT_HARDREFERENCE_H#define CLUSTER_CHAT_HARDREFERENCE_H#includeclass HardReference {public: HardReference(); virtual HardReference* obtain(); virtual void release(); virtual ~HardReference();protected: uint mHardReferenceCount;private: HardReference(HardReference* hardReference);};#endif //CLUSTER_CHAT_HARDREFERENCE_H
//// 通过引用计数来完成C++的自动内存回收,这是所有自定义类的基类//#include "HardReference.h"HardReference::HardReference() { this->mHardReferenceCount = 1;}/** * 注意,这个拷贝构造函数使用private修饰符,阻止了拷贝函数的调用**/HardReference::HardReference(HardReference *hardReference) {}HardReference::~HardReference() { this->mHardReferenceCount = 0;}/** * 如果想把自身拷贝给别人的话,只能通过指针方式传递出去, * 因为拷贝构造函数已经被设置为private, * 子类的拷贝构造函数也必须要设置为private**/HardReference* HardReference::obtain() { this->mHardReferenceCount++; return this;}/** * 添加(mHardReferenceCount > 0),防止多次析构函数的调用**/void HardReference::release() { if (this->mHardReferenceCount > 0) { this->mHardReferenceCount--; if (this->mHardReferenceCount <= 0) { delete this; } }}
在使用继承HardReference时,子类的拷贝构造函数必须是private的,如下:
//// 继承HardReference,并把拷贝构造函数设置为private,必须通过指针传递//#ifndef CLUSTER_CHAT_SESSION_H#define CLUSTER_CHAT_SESSION_H#include "base/HardReference.h"class Session : public HardReference{public: Session(const char *message); void toString(); ~Session();protected: char* mMessage;private: Session(Session &session);};#endif //CLUSTER_CHAT_SESSION_H
在使用时,不要使用delete来主动调用对象的析构函数,而是通过obtain和release方法来获取指针引用和调用析构函数。通过这种方式避免存在有效指针引用的情况下,析构函数就被调用了。
使用案例:
#include#include "Session.h"using namespace std;int main() { Session *session = new Session("Hello World!"); Session *session1 = (Session*) session->obtain(); session->toString(); session->release(); session1->toString(); session1->release(); return 0;}
每次的指针传递必须使用obtain来获取传递,而且obtain和release是成对出现的,这样有效的避免了内存泄露,而且内存的自动回收也得到实现。