谈到C++的垃圾收集策略,有一个用的比较多的方法就是引用计数在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。
试想在某场景种,类A的资源在类B和类C中都被引用,因此如果A不在使用但是B和C还有用时,此时不能释放A;而在释放B和C时只需要消除对A的引用即可;只有当B和C都不再使用A的资源之后,A才能够释放。这样一来,A,B和C在每次释放的时候都需要检查是否有依赖的引用关系,不仅编程麻烦,还降低了效率。
可以思考一下,是否有必要让A知道谁在引用它,答案是没必要,A只需要知道有多少个人在引用它,这样A只需要维护一个计数器,每次添加新的引用时计数器加1,该资源释放时计数器减1,当计数器数值为0时就释放A。
在实际设计代码的时候,可以让包含资源以及方法的类作为内部类,然后在外部用一个含有“智能引用”的计数器以及指向资源的指针的类来封装该类。这样就可以实现一个简单的含有引用计数功能、能够智能收集垃圾的封装类。一个实例代码如下:
#include <iostream>
#include <cstring>
using namespace std;
//outer class
class String {
public:
//default ctor
String() {
rep_ = new StringRep("");
cout << "String ctor: (def):" << endl;
}
//1-arg
String( const char* arg ) {
rep_ = new StringRep(arg);
cout << "String ctor: " << arg << "." << endl;
}
//copy ctor
String( String & str) {
//rep_ = new StringRep( *str.rep_ );
rep_ = str.rep_;
++str.rep_->count_;
cout << "String ctor (copy): " << str.rep_->str_ << "." << endl;
}
//dtor
~String() {
cout << "String dtor: " << rep_->str_ << ", before decrement, count is " << rep_->count_ << endl;
if(--rep_->count_ == 0)
delete rep_;
}
String& operator= ( String &rhs ) {
++rhs.rep_->count_;
if(--rep_->count_ == 0)
delete rep_;
rep_ = rhs.rep_;
return *this;
}
friend ostream& operator << ( ostream&, String& );
//inner class
class StringRep {
public:
//make String a friend of StringRep
friend class String;
friend ostream& operator << ( ostream&, StringRep& );
StringRep() {
cout << " StringRep ctor (def):" << endl;
str_ = NULL;
//initial count_
count_ = 1;
}
StringRep( const char* in ) {
cout << " StringRep ctor: " << in << '.' << endl;
str_ = new char[strlen(in) + 1];
strcpy( str_, in );
count_ = 1;
}
StringRep( StringRep& str ) {
cout << " StringRep ctor (copy): " << str.str_ << '.' << endl;
str_ = new char[strlen(str.str_) + 1];
strcpy( str_, str.str_ );
count_ = str.count_;
}
~StringRep() {
cout << " StringRep dtor: " << str_ << '.' << endl;
delete str_;
}
StringRep& operator= ( StringRep& rhs ) {
if (this == &rhs) return *this;
delete str_;
str_ = new char[strlen(rhs.str_) + 1];
strcpy( str_, rhs.str_ );
return *this;
}
private:
char* str_;
//add member data count_
int count_;
};
private:
//a pointer to StringRep
StringRep *rep_;
};
ostream& operator << ( ostream& os, String::StringRep& str ) { return os << str.str_; }
ostream& operator << ( ostream& os, String& str ) { return os << *(str.rep_); }
int main( void ) {
String a( "hello" );
// String b = "world"; is error in my computer
String b( "world" );
String c( a );
String d = a;
String e;
a = b;
e = b;
cout << "a is " << a << '.' << endl;
cout << "b is " << b << '.' << endl;
cout << "c is " << c << '.' << endl;
cout << "d is " << d << '.' << endl;
cout << "e is " << e << '.' << endl;
return 0;
}
编译运行之后可以得到如下的结果:// StringRep ctor: hello.
// String ctor: hello.
// StringRep ctor: world.
// String ctor: world.
// String ctor (copy): hello.
// String ctor (copy): hello.
// StringRep ctor: .
// String ctor (def):
// StringRep dtor: .
// a is world.
// b is world.
// c is hello.
// d is hello.
// e is world.
// String dtor: world, before decrement, count is 3
// String dtor: hello, before decrement, count is 2
// String dtor: hello, before decrement, count is 1
// StringRep dtor: hello.
// String dtor: world, before decrement, count is 2
// String dtor: world, before decrement, count is 1
// StringRep dtor: world.