/** * 书本:【ThinkingInC++】 * 功能:引用计数,可以知道有多少个对象指向这个对象。 * 时间:2014年10月5日14:28:11 * 作者:cutter_point */ #include "../require.h" //这个文件是为了检验一些错误的,这个可以用#include<cassert>代替,但是相应的函数也要改 #include <string> #include <iostream> using namespace std; class Dog { //私有成员有string的名字,有引用的计数值,构造函数私有化,不让其他外部对象随便生成新的存储空间 //operator=私有化,理由同上,不随便产生新的存储空间 string nm; int refcount; //用来计数,这个类的引用个数 //这个是构造函数,初始化数据 Dog(const string& name) : nm(name), refcount(1) {cout<<"Creating Dog: "<<*this<<endl;} //私有的operator=也是避免隐式调用构造函数 Dog& operator = (const Dog& rv); public: //然后创建一个Dog对象通过静态方法创建,就是在类开始的地方初始化 static Dog* make(const string& name) {return new Dog(name);} //拷贝构造函数 Dog(const Dog& d) : nm(d.nm+" copy"), refcount(1) {cout<<"Dog copy-constructor: "<<*this<<endl;} //析构函数 ~Dog() {cout<<"Deleting Dog: "<<*this<<endl;} //用一个函数来增加一个Dog引用计数,attach void attach() {++refcount; cout<<"Attached Dog: "<<*this<<endl;} //一个函数减少引用计数 void detach() {//减少一个对象引用 require(refcount != 0); cout<<"Detaching Dog: "<<*this<<endl; //有条件地删除这个空间 if(--refcount == 0) delete this; } //判定是否引用计数是否为1,就是意味着没有别的对象指向这块内存单元,然后返回this //如果大于1说明有别的对象指向这个内存单元,那么就复制这块内存单元,创建一个新的内存块 Dog* unalias() { cout<<"Unaliasing Dog: "<<*this<<endl; //如果等于1,那么没有其他对象引用它,直接返回当前对象 if(refcount == 1) return this; --refcount; //大于1那么就要把原来的对象复制出来一份新的存储空间 return new Dog(*this); } //修改名字 void rename(const string& newName) { nm=newName; cout<<"Dog renamed to: "<<*this<<endl; } //重载操作符<<输出流 friend ostream& operator << (ostream& os, const Dog& d) { return os<<"["<<d.nm<<"], rc = "<<d.refcount; } }; class DogHouse { Dog* p; //一个指向Dog类的对象 string houseName; public: //构造函数,创建一个新的内存 DogHouse(Dog* dog, const string& house) : p(dog), houseName(house) {cout<<"Created DogHouse: "<<*this<<endl;} //拷贝构造函数 DogHouse(const DogHouse& dh) : p(dh.p), houseName("copy-constructed "+dh.houseName) {//用一个函数来增加一个Dog引用计数,attach //拷贝一次吧dh.p的指针赋值给p,没有创建新空间,就是增加了一个引用 p->attach(); cout<<"DogHouse copy-constructor: "<<*this<<endl; } //operator=的运算符重载 DogHouse& operator=(const DogHouse& dh) { //operator=这里调用了赋值,创建了新的空间,会自动调用了构造函数 //避免自赋值 if(&dh != this) { houseName=dh.houseName+" = used"; //所以这里构造函数的时候增加了一个引用在,减少引用,看是否最后一个,没有别的对象在使用它 p->detach(); p=dh.p; //传送指针,给这个对象增加一个引用对象 p->attach(); //增加一个引用 } cout<<"DogHouse operator= : "<<*this<<endl; return *this; } //析构函数,减少引用 ~DogHouse() { cout<<"DogHouse destructor: "<<*this<<endl; p->detach(); //析构一个对象的时候调用这个析构,如果还有对象在引用就不回收空间,如果这是最后个直接回收空间 } void renameHouse(const string& newName) {houseName=newName;} //判定是否引用计数是否为1,就是意味着没有别的对象指向这块内存单元,然后返回this //如果大于1说明有别的对象指向这个内存单元,那么就复制这块内存单元,创建一个新的内存块 void unalias() {p=p->unalias();} void renameDog(const string& newName) {unalias(); p->rename(newName);} Dog* getDog() {unalias(); return p;} friend ostream& operator << (ostream& os, const DogHouse& dh) { return os<<"["<<dh.houseName<<"] contains "<<*dh.p; } }; int main() { DogHouse fidos(Dog::make("Fido"), "FidoHouse"), spots(Dog::make("Spot"), "SpotHouse"); cout<<"开始构造函数"<<endl; DogHouse bobs(fidos); cout<<"拷贝构造函数之后"<<endl; cout<<"fidos:"<<fidos<<endl; cout<<"spots:"<<spots<<endl; cout<<"bobs:"<<bobs<<endl; cout<<"进入赋值运算 spots = fidos"<<endl; spots=fidos; cout<<"退出赋值运算 spots = fidos"<<endl; cout<<"spots:"<<spots<<endl; cout<<"进入自赋值"<<endl; bobs=bobs; cout<<"退出自赋值"<<endl; cout<<"bobs:"<<bobs<<endl; cout<<"开始改名字"<<endl; bobs.getDog()->rename("Bob"); cout<<"退出改名"<<endl; return 0; }
大部分注释都是直接写到代码上的,最近感觉自己越来越无知了和自大了!!! 赶紧去学习一下压压惊= =
吓死哥了。
原文地址:http://blog.csdn.net/cutter_point/article/details/39803015
原文地址:http://blog.csdn.net/cutter_point/article/details/39803015