【ThinkingInC++】63、引用计数

来源:互联网 发布:ipadmini淘宝试用在哪 编辑:程序博客网 时间:2024/05/30 22:58
/*** 书本:【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;}



大部分注释都是直接写到代码上的,最近感觉自己越来越无知了和自大了!!! 赶紧去学习一下压压惊= =

吓死哥了。

0 0
原创粉丝点击