zoukankan      html  css  js  c++  java
  • 智能指针(二)--练习

    智能指针--练习

    #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;
    }
    
  • 相关阅读:
    Linux ,Ubuntu 分区建议大小
    [No000019A]【波浪理论精典教学课程】
    CS(计算机科学)知识体
    如何量化考核技术人的KPI?
    Linux系统的命令应该如何记?
    数学和物理太难?这些 GIF 让你秒懂抽象概念
    加密数字货币的 7 个致命悖论
    量子力学中,全体自然数之和是负十二分之一,物理意义是什么?
    30岁左右的人,来谈谈你犯了哪些错误?
    一篇文章学懂Shell脚本,最简明的教程在这里
  • 原文地址:https://www.cnblogs.com/FlyerBird/p/12336861.html
Copyright © 2011-2022 走看看