【足迹C++primer】46、动态存储类

动态存储类

StrVec Class Design

StrVec Class Definition

class StrVec
{
public:
    //构造函数
    StrVec():elements(nullptr), first_free(nullptr), cap(nullptr){}

    //用initializer_list<string>初始化参数列表
    StrVec(initializer_list<string> il):StrVec(il){}

    //拷贝构造函数
    StrVec(const StrVec&);
    //拷贝赋值运算符
    StrVec &operator=(const StrVec&);
    //析构函数
    ~StrVec();

    void push_back(const string&);  //拷贝元素进入队列
    size_t size() const {return first_free-elements;}   //队列存放元素个数
    size_t capacity() const {return cap-elements;}      //队列存储空间大小
    string* begin() const {return elements;}            //起始指针
    string* end() const {return first_free;}            //第一个为空的元素
    //。。。

private:
//    vector<string> vs;
    allocator<string> alloc;    //分配元素
    //判断是否要添加新的内存空间
    void chk_n_alloc()
    {
        if(size() == capacity())        //判断数据长度是否已经达到分配空间的上限
            reallocate();       //如果是,那么就重新分配空间
    }
    //用到拷贝构造函数,拷贝赋值运算符,析构函数的工具函数
    pair<string*, string*> alloc_n_copy(const string*, const string*);
    void free();        //销毁这个类的元素,并释放空间
    void reallocate();  //重新分配空间并且把原来的元素移动到新空间上

    string *elements;   //指向这个队列的第一个元素
    string *first_free; //指向这个队列第一个为空的元素,即最后元素的后一位
    string *cap;        //指向最后一个空间位置后一位
};


English explain:
• The default constructor (implicitly) default initializes alloc and (explicitly)
initializes the pointers to nullptr, indicating that there are no elements.
• The size member returns the number of elements actually in use, which is
equal to first_free - elements.
• The capacity member returns the number of elements that the StrVec can
hold, which is equal to cap - elements.
• The chk_n_alloc causes the StrVec to be reallocated when there is no room
to add another element, which happens when cap == first_free.
• The begin and end members return pointers to the first (i.e., elements) and
one past the last constructed element (i.e., first_free), respectively.


Using construct

void StrVec::push_back(const string& s)
{
    chk_n_alloc();      //检查看是否需要重新分配空间
    //吧元素s拷贝到first_free之后
    alloc.construct(first_free++, s);   //一个空间就是一个string大小
}

The alloc_n_copy Member
拷贝构造函数,拷贝赋值运算符,析构函数的工具函数

inline
pair<string*, string*>
StrVec::alloc_n_copy(const string* b, const  string* e) //开始和结尾指针
{
    //要拷贝对象要求的空间大小
    auto data=alloc.allocate(e-b);
    //吧b,e之间的元素拷贝到data中
    //返回一个pair
    pair<string*, string*> p={data, uninitialized_copy(b, e, data)};
    return p;
}

The free Member

void StrVec::free()
{
    //如果头指针本身就是空的,那么就不用释放内存了,因为就是空的
    if(elements)
    {
        //倒序,一个个的吧元素删除,内存释放
        for(auto p=first_free ; p != elements ; /* empty )
            alloc.destroy(--p);
        alloc.deallocate(elements, cap-elements);
/*
deallocate(p,n);         释放内存,
在类型为T*的指针p指向的地址,保存着n个对象,
运行deallocate之前调用destroy是用户的责任。
Once the elements have been destroyed, we free the space that this StrVec
allocated by calling deallocate */
    }
}

这里有一个错误演示,我也还没搞懂为什么报错,调了半天没出来,只要留在这里,以后解决了。
void StrVec::free()
{
    if(elements)
    {
        for_each(first_free, elements, [this](string* p){alloc.destroy(--p);});
        alloc.deallocate(elements, cap-first_free);
    }
}

2014年7月18日17:57:47

改正错误:
void StrVec::free()
{
    if(elements)
    {
        for_each(first_free, elements, [this](string& p){alloc.destroy(&p);});
        alloc.deallocate(elements, cap-first_free);
    }
}


Copy-Control Members

StrVec::StrVec(const StrVec &s)
{
    // call alloc_n_copy to allocate exactly as many elements as in s
    auto newdata=alloc_n_copy(s.begin(), s.end());  //pair类型
    elements=newdata.first;
    first_free=cap=newdata.second;
    //The return value from alloc_n_copy is a pair of pointers.

}

The destructor calls free:

inline
StrVec::~StrVec()
{
    free();
}

拷贝赋值运算符

StrVec &StrVec::operator=(const StrVec &rhs)
{
    //先把要赋值的值拷贝下来
    auto data=alloc_n_copy(rhs.begin(), rhs.end());
    free();     //吧右边的值销毁
    //重新赋予给左边
    elements=data.first;
    first_free=cap=data.second;

    return *this;
}

Moving, Not Copying, Elements during Reallocation

move在头文件utility里面

The reallocate Member

void StrVec::reallocate()
{
    //直接把当前容量扩充到2倍
    auto newcapacity=size() ? 2*size() : 1 ;
    //allocate新内存
    auto newdata=alloc.allocate(newcapacity);   //申请新空间
    //吧元素重老的地方移到新的地方
    auto dest=newdata;      //指出新空间第一个空位置
    auto elem=elements;     //老队列的第一个元素
    //全部构造到新的里面去
    for(size_t i=0 ; i != size() ; ++i)
        alloc.construct(dest++, std::move(*elem++));    //循环吧老的元素移动到新的上
    free();     //移完了,把老空间全部释放

    //重新更新数据指针
    elements=newdata;
    first_free=dest;
    cap=elements+newcapacity;
}

PS:不要问我,为什么你的英语突然变得那么厉害了!!!我是不会告诉你我的那本中文版的C++ primer被我搞掉了的!!!!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值