行为像(值/指针)的类

行为像值的类

  • 每个类的数据成员都有一份自己的拷贝.不共享数据成员.
#include <iostream>
#include <string>
#include <memory>

using namespace std;

class HasPtr{
public:
    HasPtr():ps(make_shared<string>()),num(0) {}
    HasPtr(const string& s,int sz=0):ps(make_shared<string>(s)),num(sz) {}
    HasPtr(const HasPtr& rhs) {
        ps = make_shared<string>(*rhs.ps);
        num = rhs.get_number();
    }
    HasPtr& operator= (const HasPtr& rhs) {
        ps = make_shared<string>(*rhs.ps);
        return *this;
    }
    int get_number() const { return num; }
    int get_number() { return num; }
    shared_ptr<string> get_ptr() { return ps; }
    shared_ptr<string> get_ptr() const { return ps; }
private:
    int num;
    shared_ptr<string> ps;
};
int main() {
    HasPtr temp1("hello");
    HasPtr temp2 = temp1;
    cout << "string s= " << *temp1.get_ptr() << endl;
    cout << "temp2 s = " << *temp2.get_ptr() << endl;


    return 0;
}

行为像指针的类

  • 直接使用shared_ptr<>来管理资源
  • 通过普通指针设计引用计数来实现资源管理
引用计数设计原则
  1. 普通构造创建计数器
  2. 拷贝构造函数,拷贝数据成员,或者指针本身,同时计数器自增
  3. 拷贝赋值运算,递减左侧运算对象计数器,递增右侧运算对象计数器,并判断计数器==0
  4. 析构递减计数器,==0回收内存
    HasPtr_ptr1.cpp
#include <iostream>
#include <string>

using namespace std;

class HasPtr {
    public:
        HasPtr(const string& s = string(),int sz = 0):ps(new string(s)),i(sz),use(new size_t(1)) {}
        HasPtr(const HasPtr& rhs):
            ps(rhs.ps),i(rhs.i),use(rhs.use) {
                ++*use;
            }
        HasPtr& operator= (const HasPtr& rhs) {
            ++*rhs.use;
            if (--*use == 0) {
                cout << "reference count = 0" << endl;
                delete ps;
                delete use;
            }
            ps = rhs.ps;
            i = rhs.i;
            use = rhs.use;
            return *this;
        }
        ~HasPtr() {
            if (--*use == 0) {
                cout << "reference count = 0" << endl;
                delete ps;
                delete use;
            }
        }
        string get_ps() { return *ps; }
        string get_ps() const { return *ps; }
        int get_i() { return i; }
        int get_i() const { return i; }
    private:
        string* ps;
        int i;
        size_t* use;
};


int main() {
    HasPtr temp1("hello",11);
    HasPtr temp2("world",23);
    temp1 = temp2;
    cout << "temp1.i " << temp1.get_i() << "\n";
    HasPtr temp3 = temp2;
    cout << "temp3.i " << temp3.get_i() << "\n";
    return 0;
}

HasPtr_ptr2.cpp

#include <iostream>
#include <string>
#include <vector>
#include <initializer_list>

using namespace std;

class HasPtr {
    public:
        HasPtr():ps(new vector<string>),use(new int(1)) {}
        HasPtr(initializer_list<string> i1):ps(new vector<string>(i1)),use(new int(1)) {}

        HasPtr(HasPtr& rhs):ps(rhs.ps),use(rhs.use) { ++*use; }

        HasPtr& operator= (HasPtr& rhs) {
            ++*rhs.use;
            if (--*use == 0) {
                delete ps;
                delete use;
            }
            use = rhs.use;
            ps = rhs.ps;

            return *this;
        }
        ~HasPtr() {
            if (--*use == 0) {
                cout << " destructor reference count " << endl;
                delete ps;
                delete use;
            }
        }
        void push_back(const string& t) { ps->push_back(t); }
        void pop_back() {
            if (!ps->empty())
                ps->pop_back();
            else
                cout << " vector<string> is empty " << endl;
        }
        size_t size() const { return ps->size(); }
        size_t get_use() const { return *use; }
    private:
        vector<string>* ps;
        int* use;
};
int main() {
    HasPtr temp1 = {"a","b","c"};
    {
        HasPtr temp2 = temp1;
        temp2.push_back("d");
        cout << "temp2.size()= " << temp2.size() << endl;
        cout << "temp1.size()= " << temp1.size() << endl;
        cout << "temp1.use = " << temp1.get_use() << "  temp2.use = " << temp2.get_use() << endl;
    }

    cout << "temp1.use = " << temp1.get_use() << endl;
    return 0;
}

书上给出的标程:
HasPtr_ptr3.cpp

#include <iostream>
#include <string>

using namespace std;

class HasPtr {
    public:
        HasPtr(const string& s=string()):ps(new string(s)),i(0),use(new size_t(1)) {}
        HasPtr(const HasPtr& p):
            ps(p.ps),i(p.i),use(p.use) { ++*use; }
        HasPtr& operator=(const HasPtr& rhs) {
            ++*rhs.use;
            if (--*use == 0) {
                delete ps;
                delete use;
            }
            ps = rhs.ps;
            use = rhs.use;
            i = rhs.i;
            return *this;
        }
        HasPtr& operator=(const string& rhs) {
            *ps = rhs;
            return *this;
        }
        string& operator* () { return *ps; }
        ~HasPtr() {
            if (--*use == 0) {
                delete ps;
                delete use;
            }
        }
    private:
        string* ps;
        int i;
        size_t* use;
};
int main() {
    HasPtr h("ni mom!");
    HasPtr h2 = h;
    h = "hi dad!";
    cout << "h: " << *h << endl;
    cout << "h2: " << *h2 << endl;
    return 0;
}

StrBlob类通过定义拷贝控制操作使其行为像值

my_StrBlob.h

#ifndef MY_STRBLOB_H
#define MY_STRBLOB_H

#include <vector>
#include <string>
#include <initializer_list>
#include <memory>
#include <stdexcept>

using namespace std;

class StrBlobPtr;
class StrBlob {
    friend class StrBlobPtr;
    public:
        using size_type = vector<string>::size_type;

        StrBlob():data(make_shared<vector<string>>()) {}
        StrBlob(initializer_list<string> i1):data(make_shared<vector<string>>(i1)) {}
        StrBlob(vector<string>* p):data(p) {}
        StrBlob(StrBlob& rhs):data(make_shared<vector<string>> (*rhs.data)) {}
        StrBlob& operator= (StrBlob& rhs) {
            data = make_shared<vector<string>> (*rhs.data);
            return *this;
        }

        size_type size() const { return data->size(); }
        bool empty() const { return data->empty(); }

        void push_back(const string& t) { data->push_back(t); }
        void pop_back();

        string& front();
        string& front() const;

        string& back();
        string& back() const;

        StrBlobPtr begin();
        StrBlobPtr end();

        StrBlobPtr begin() const;
        StrBlobPtr end() const;

    private:
        shared_ptr<vector<string>> data;
        void check(size_type i,const string& msg) const;
};

inline void StrBlob::check(size_type i,const string& msg) const {
    if(i >= data->size())
        throw out_of_range(msg);
}

inline string& StrBlob::front() {
    check(0,"front");
    return data->front();
}
inline string& StrBlob::front() const {
    check(0,"const front");
    return data->front();
}

inline string& StrBlob::back() {
    check(0,"back");
    return data->back();
}
inline string& StrBlob::back() const {
    check(0,"const back");
    return data->back();
}

inline void StrBlob::pop_back() {
    check(0,"ss");
    data->pop_back();
}

class StrBlobPtr {
    friend bool eq(const StrBlobPtr&,const StrBlobPtr&);
    public:
        StrBlobPtr():curr(0) {}
        StrBlobPtr(StrBlob& a,size_t sz = 0):wptr(a.data),curr(sz) {}
        StrBlobPtr(const StrBlob& a,size_t sz = 0):wptr(a.data),curr(sz) {}

        string& deref() const;
        string& deref(int off) const;
        StrBlobPtr& incr();
        StrBlobPtr& decr();
    private:
        shared_ptr<vector<string>> check(size_t,const string&) const;
        weak_ptr<vector<string>> wptr;
        size_t curr;
};
inline shared_ptr<vector<string>> StrBlobPtr::check(size_t i,const string& msg) const {
    auto ret = wptr.lock();
    if (!ret)
        throw runtime_error("x");
    if (i >= ret->size())
        throw out_of_range(msg);
    return ret;
}
inline string& StrBlobPtr::deref() const {
    auto p = check(curr," ");
    return (*p)[curr];
}
inline string& StrBlobPtr::deref(int off) const {
    auto p = check(curr + off," ");
    return (*p)[curr + off];
}

inline StrBlobPtr& StrBlobPtr::incr() {
    check(curr,"curr range");
    ++curr;
    return *this;
}
inline StrBlobPtr& StrBlobPtr::decr() {
    curr--;
    check(-1,"d");
    return *this;
}

inline StrBlobPtr StrBlob::begin() {
    return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end() {
    auto ret = StrBlobPtr(*this,data->size());
    return ret;
}
inline StrBlobPtr StrBlob::begin() const {
    return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end() const {
    auto ret = StrBlobPtr(*this,data->size());
    return ret;
}

inline bool eq(const StrBlobPtr& lhs,const StrBlobPtr& rhs) {
    auto l = lhs.wptr.lock();
    auto r = rhs.wptr.lock();
    if (l == r)
        return (!r || lhs.curr == rhs.curr);
    else
        return false;
}
inline bool neq(const StrBlobPtr& lhs,const StrBlobPtr& rhs) {
    return !eq(lhs,rhs);
}
#endif

测试

test.cpp

#include <iostream>
#include "my_StrBlob.h"

using namespace std;

int main() {
    StrBlob b1;
    {
        StrBlob b2 = {"a","an","the"};
        b1 = b2;
        b2.push_back("about");
        cout << "b2.size() = " << b2.size() << endl;
        cout << "b2.front() = " << b2.front() << " b2.end() = " << b2.back() << endl;
    }
    cout << "b1.size() = " << b1.size() << endl;
    cout << "b1.front() = " << b1.front() << " b1.back() = " << b1.back() << endl;


    StrBlob b3 = b1;
    b3.push_back("next");
    cout << "b3.size() = "  << b3.size() << endl;
    cout << "b3.front() = " << b3.front() << " b3.back() = " << b3.back() << endl;

    cout << "all of b1" << endl;
    for (auto it = b1.begin(); neq(it,b1.end()); it.incr())
        cout << " it.deref()= " << it.deref() << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值