C++沉思录读书笔记(6章)-句柄:第一部分

来源:岁月联盟 编辑:exp 时间:2011-11-11

 

创建代理会复制所代理的对象,如何避免这些复制呢?

       可以通过句柄(handle)类来实现。句柄类和智能指针有点类似,通过重载句柄类的*和->操作符,可将句柄类改造称为智能指针。

       从效果上来说,handle就是一种只包含单个对象的容器,它通过允许多个handle对象指向同一个对象来避免复制。

       定义句柄类,我们还需要新定义一个类来容纳被引用类对象的引用计数和被引用类对象本身。

示例代码如下

#include <iostream> 

using namespace std; 

class Point 

private: 

    int xval, yval; 

public: 

    Point() : xval(0), yval(0) 

    { 

        cout << "Point" << endl; 

    } 

    Point(int x, int y) : xval(x), yval(y) 

    { 

        cout << "Point" << endl; 

    } 

    int x() const { return xval;} 

    int y() const { return yval;} 

    Point& x(int xv) 

    { 

        xval = xv; 

        return *this; 

    } 

    Point& y(int yv) 

    { 

        yval = yv; 

        return *this; 

    } 

    ~Point() 

    { 

        cout << "~Point" << endl; 

    } 

}; 

class UPoint    //这个类对用户来说是不可见的, 就是一个间接层 

    friend class Handle; 

    Point p;    //Point 对象 

    int u;     //计数器 

 

    UPoint():u(1)   //提供所有的point的构造方式 

    { 

        cout << "UPoint::" << u << endl; 

    } 

    UPoint(int x, int y):p(x, y), u(1) 

    { 

        cout << "UPoint::" << u << endl; 

    } 

    UPoint(const Point &p0) : p(p0), u(1) 

    { 

        cout << "UPoint::" << u << endl; 

    } 

    ~UPoint() 

    { 

        cout << "~UPoint::" << u << endl; 

    } 

}; 

class Handle 

private: 

    UPoint *up;    //和间接层UPoint打交道了 

public: 

    Handle(); 

    Handle(int, int); 

    Handle(const Point&); 

    Handle(const Handle&); 

    Handle& operator=(const Handle&); 

    ~Handle(); 

    int x() const; 

    Handle& x(int); 

    int y() const; 

    Handle& y(int); 

}; 

 

Handle::Handle():up(new UPoint) 

    cout << "Handle::" <<up->u << endl;  

 

Handle::Handle(int x, int y):up(new UPoint(x, y)) //按创建Point的方式构造handle,handle->UPoint->Point 

    cout << "Handle::" <<up->u << endl; 

 

Handle::Handle(const Point &p):up(new UPoint(p)) //创建Point的副本 

    cout << "Handle::" <<up->u << endl; 

 

Handle::~Handle() 

    if(--up->u == 0) 

    { 

        cout << "~Handle::" <<up->u << endl; 

        delete up; 

    } 

    else 

    { 

        cout << "~Handle::" <<up->u << endl; 

    } 

 

Handle::Handle(const Handle &h):up(h.up) 

    ++up->u;       //此处复制的是handle,但是底层的point对象并未复制,只是引用计数加1 

    cout << "Handle::" <<up->u << endl; 

 

Handle& Handle::operator=(const Handle &h) 

    ++h.up->u;       //右边的对象引用计数加1,左边的减1 

    if(--up->u == 0) 

        delete up; 

    up = h.up; 

    cout << "Handle::" <<up->u << endl; 

    return *this; 

 

int Handle::x() const 

    return up->p.x(); 

 

int Handle::y() const 

    return up->p.y(); 

 

Handle& Handle::x(int x0)//假设句柄为指针语义 

    up->p.x(x0); 

    return *this; 

 

Handle& Handle::y(int y0) 

    up->p.y(y0); 

    return *this; 

 

/*

Handle& Handle::x(int x0)//假设句柄为值语义(写时复制)

{

    if(up->p != 1)

    {

        --up->u;

        up = new UPoint(up->p);

    }

    up->p.x(x0);

    return *this;

}

 

Handle& Handle::y(int y0)

{

    if(up->p != 1)

    {

        --up->u;

        up = new UPoint(up->p);

    }

    up->p.y(y0);

    return *this;

}

*/ 

 

void f(Handle h)   //测试函数,复制handle,但未复制Point 

    cout << h.x() << h.y() << endl; 

 

int main() 

    Handle h(3,5); 

    cout << h.x() << h.y() << endl; 

    f(h); 

 

    Point o(10,9); 

    Handle a(o); 

    Handle b(a); 

    return 0; 

}   

 

作者 yucan1001