Smart pointers (two) - Practice

Smart pointers - Practice

#include<iostream>
#include<string>
#include<vector>
#include<memory>
#include<fstream>
#include<initializer_list>
using namespace std;
class StrBlobPtr; //仅仅是声明,在该类为完全定义完整之前,只能使用其类型,而不能调用其成员和函数
class StrBlob {
    friend class StrBlobPtr;
public:
    typedef vector<string>::size_type size_type;
    StrBlob();
    StrBlob(initializer_list<string>il);
    StrBlob(vector<string>stp);
    StrBlob(shared_ptr<vector<string>>tp);
    size_type size() const { return data->size();};
    bool empty()const { return data->empty(); }
    //add & delete
    void push_back(const string& t) { data->push_back(t); }
    void pop_back();
    //visit data
    string& front();
    string& front()const;
    string& back();
    string& back()const;
    //begin和end,返回指向自身的StrBlobPtr,此时不能被定义,知道strBlobPtr被定义完了之后才行,否则C2027
    StrBlobPtr begin();
    StrBlobPtr end();
    StrBlobPtr begin()const;// const版本使得StrBlobPtr可以指向const的StrBlob
    StrBlobPtr end()const; 
private:
    shared_ptr<vector<string>>data;
    //check the index of data
    void check(size_type i, const string& msg)const;
};
StrBlob::StrBlob():data(make_shared<vector<string>>()) {}
StrBlob::StrBlob(initializer_list<string>il):
    data(make_shared<vector<string>>(il)) {}
StrBlob::StrBlob(vector<string> stp):
    data(make_shared<vector<string>>(stp)){}
StrBlob::StrBlob(shared_ptr<vector<string>> tp):data(tp){}
void StrBlob::check(size_type i, const string& msg)const
{
    if (i >= data->size())
        throw out_of_range(msg);
}
string& StrBlob::front()
{
    check(0, "front on the empty Strblob");
    return data->front();
}
string& StrBlob::front()const
{
    check(0, "front on the empty Strblob");
    return data->front();
}
string& StrBlob::back()
{
    check(0, "back on the empty Strblob");
    return data->back();
}
string& StrBlob::back()const 
{
    check(0, "back on the empty Strblob");
    return data->back();
}
void StrBlob::pop_back()
{
    check(0, "pop_back on the empty Strblob");
    return data->pop_back();
}
class StrBlobPtr {
public:
    StrBlobPtr() :curr(0) {}
    StrBlobPtr(StrBlob &a,size_t sz=0):curr(sz),wptr(a.data) {}
    StrBlobPtr(const StrBlob& a, size_t sz = 0) :curr(sz), wptr(a.data) {}
    string& deref()const;//解引用获取元素
    StrBlobPtr& incr();  //前缀递增
    StrBlobPtr& decr();  //递减
    bool equal(const StrBlobPtr& , const StrBlobPtr& );
private:
    //如果检查成功,就check返回一个指向vector的shared_ptr
    shared_ptr<vector<string>> check(size_t, const string&)const;
    //保存一个weak_ptr,意味着底层vector可能被销毁
    weak_ptr<vector<string>>wptr;
    size_t curr;//在数组中当前的位置
};
shared_ptr<vector<string>> StrBlobPtr::check(size_t i , const string& msg)const {
    auto ret = wptr.lock(); //查看是否vector还存在
    if (!ret)
        throw runtime_error("unbound StrBlobPtr");
    if (i >= ret->size())
        throw out_of_range("msg");
    return ret;     //否则返回指向vector的shared_ptr
}
string& StrBlobPtr::deref()const {
    //调用check,检查vector是否安全以及curr是否在范围内
    auto p = check(curr, "dereference past end");
    return (*p)[curr];      //解引用p获得vector,然后使用下标操作提取并返回curr位置上的元素
}
StrBlobPtr& StrBlobPtr::incr(){
    //如果curr已经指向容器的尾后位置,则不能引用它
    check(curr, "increment past end of StrBlobPtr");
    ++curr;//推进当前位置
    return *this;
} 
StrBlobPtr& StrBlobPtr::decr()
{
    --curr;       
    check(-1, "decrement past begin of StrBlobPtr");
    return *this;
}
bool StrBlobPtr::equal(const StrBlobPtr& beg, const StrBlobPtr& end)
{

    auto b = beg.wptr.lock(), e = end.wptr.lock();
    if (beg.curr == end.curr)
        return true;
    else
        return false;
}
StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}
StrBlobPtr StrBlob::begin()const
{
    return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()const
{
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}
void readline(string ifile, vector<string> &str) {//将文件内容读入到一个string的vector容器中去
    vector<string>::iterator it;
    string tmp;
    str.clear();
    ifstream openfile(ifile + ".txt", ifstream::in);  //以读模式打开一个文件                                    
    while (getline(openfile, tmp)) {        //没有到达文件的尾部
                //读入一行
        str.push_back(tmp);         //每一行作为独立元素存入vector中
    }
    if (str.empty()) {              //没有数据,直接返回
        cout << "No data?!" << endl;
        return;
    }
    /*
    it = str.begin();
    for (; it != str.end(); it++)   //输出文件内容(存入vector中的)
        cout << (*it) << endl;
    */
    openfile.close();               //关闭文件流
}
auto init_vec() {
    auto p = new vector<int>;
    return p;
}
auto init_vec_shared() {
    auto p = make_shared<vector<int>>();
    return p;
}
auto read_vec(istream&in ,vector<int>* p) {
    int tmp = 0;
    while (in>>tmp) {       
        p->push_back(tmp);
    }
    return p;
}
auto read_vec_shared(istream& in, shared_ptr<vector<int>>p) {
    int tmp = 0;
    while (in >> tmp) {
        p->push_back(tmp);
    }
    return p;
}
void dis_vec(vector<int>* p) {
    for (auto i = p->begin(); i != p->end(); i++) {
        cout << *i << endl;
    }
    delete p;
}
void dis_vec_shared(shared_ptr<vector<int>>p) {
    for (auto i = p->begin(); i != p->end(); i++) {
        cout << *i << endl;
    }
}
void process(shared_ptr<int>ptr) {
    cout << *ptr << endl;
}
int main(void) {

    //dis_vec(read_vec(cin, init_vec()));  从键盘读入,然后输出
    //dis_vec_shared(read_vec_shared(cin, init_vec_shared())); 从键盘读入,然后输出

    //从文件读入,然后输出
    vector<string>st;
    readline("test", st);
    StrBlob a(st);
    StrBlobPtr b(a.begin());
    while (!b.equal(b,a.end())) {
        cout << b.deref() << endl;
        b.incr();
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/FlyerBird/p/12336861.html