C++primer_拷贝控制之13.26联系控制成员实现类值行为

这是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:
        typedef vector<string>::size_type size_type;
        StrBlob();
        StrBlob(initializer_list<string>il);
        StrBlob(vector<string>*p);
        StrBlob(StrBlob&s);
        StrBlob&operator=(StrBlob&rhs);
        size_type size() const { return data->size(); }
        void push_back(const string &t) { data->push_back(t); }
        void pop_back();
        string &front();
        const string &front()const;
        string &back();
        const string &back()const;
        StrBlobPtr begin();
        StrBlobPtr end();
        StrBlobPtr begin()const;
        StrBlobPtr end()const;
    private:
        shared_ptr<std::vector<std::string>>data;
        void check(size_type i, const string &msg)const;
};
class StrBlobPtr//这个类是智能指针管理类
{
    friend class StrBlob;
    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;//若检查成功,check返回一个指向vector的shared_ptr指针
    weak_ptr<vector<string>>wptr;//在这里保存一个weak_ptr,那么底层元素可能被销毁
    size_t curr;//在数组当前位置

};

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

inline void StrBlob::check(size_type i, const std::string &msg)const
{
    if (i >= data->size())
        throw out_of_range(msg);
}
inline string&StrBlob::front()
{
    check(0, "front on empty StrBlog");
    return data->front();
}
inline string&StrBlob::back()
{
    check(0, "back on empty StrBlog");
    return data->back();
}
inline const string&StrBlob::front() const
{
    check(0, "front on empty StrBlog");
    return data->front();
}
inline const string&StrBlob::back() const
{
    check(0, "back on empty StrBlog");
    return data->back();
}
inline void StrBlob::pop_back()
{
    check(0, "pop_back on empty StrBlog");
    return data->pop_back();

}

//第StrBlobPtr类函数定义开始
inline shared_ptr<vector<string>>StrBlobPtr::check(size_t i, const string &msg)const
{
    auto ret = wptr.lock();
    if (!ret)
        throw runtime_error("unbound StrBlobPtr");
    if (i >= ret->size())
        throw out_of_range(msg);
    return ret;//检查容器是否存在,存在的话返回vector的shared_ptr计数
}
inline string &StrBlobPtr::deref(int off)const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr + off];
}
inline string &StrBlobPtr::deref()const
{
    auto p = check(curr, "dereference past end");
    return (*p)[curr];
}
inline StrBlobPtr&StrBlobPtr::incr()//前缀递增
{
    check(curr, "increment past end of StrBlobPtr");//先做检查,若现在已经指向响亮的尾后位置,那么就不能递增他
    ++curr;
    return *this;
}
inline StrBlobPtr&StrBlobPtr::decr()//前缀递减
{
    --curr;
    check(-1, "Decrement past begin of StrBlobPtr");//先做检查,若之前已经指向0,那么现在的地址就是非法地址,那么就抛出异常;

    return *this;
}

//StrBlob的begin和end操作
inline StrBlobPtr StrBlob::begin()
{
    return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end()
{
    auto ret = StrBlobPtr(*this, data->size());
    return ret;
}
//StrBlob的begin和end操作const版本
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&lns, const StrBlobPtr &rhs)
{
    auto l = lns.wptr.lock(), r = rhs.wptr.lock();//函数的目的是为了确认两个容器底层是否为同一个容器
    if (l == r)
        return(!r || lns.curr == rhs.curr);//若是两个指针为空,或者元素位置相同那么他们就相同;
    else
        return false;
}
inline bool neq(const StrBlobPtr&lns, const StrBlobPtr &rhs)
{
    return !eq(lns, rhs);
}
#endif

头文件main.cpp如下

#include "StrBlob.h"
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{


    StrBlob b1;
    StrBlob b2 = { "a", "an", "the" };
    b1 = b2;
    b2.push_back("about");
    cout << "b2大小为" << b2.size() << endl;
    cout << "b2首尾元素为" << b2.front() <<" "<< b2.back()<<endl;
    cout << "b1大小为" << b1.size() << endl;
    cout << "b1首尾元素为" << b1.front() << " " << b1.back() << endl;
    //结果证明了此时的b1和b2已经不再是统一底层元素了

    StrBlob b3 = b1;
    b3.push_back("next");
    cout << "b3大小为" << b3.size() << endl;
    cout << "b3首尾元素为" << b3.front() << " " << b3.back() << endl;

    cout << "b1全部元素:" << endl;
    for (auto it =b1.begin();neq(it,b1.end());it.incr())
    {
        cout << it.deref() << endl;
    }
    system("pause");
    return 0;
}

此时运行结果如下:
这里写图片描述

但是请记住,当把所有函数定义为内联函数时,请不要将执行类与实现分离的傻瓜式分离,因为内联函数本身就是在头文件内部定义的,与此同时,若是将实现放在类对应的cpp文件中,那么就会导致失败,而且函数对于编译器是不可见的
效果如下:
这里写图片描述
所以在一般情况下,内联函数必须放在头文件中,这样对编译器来说是安全可见 的。在多文件程序中,由于inline函数可能会被编译器插入到每个文件里面,所以如果把inline函数放在某个cpp文件中,编译器可能不能找到这个inline函数而出错,但如果放在头文件中,由于编译器总是先处理所有的头文件,所以能先找到inline函数的定义。这样就是为了避免编译器 的安全性。

转载于:https://www.cnblogs.com/VCctor/p/5100678.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值