談到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.