• 【足迹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被我搞掉了的!。。!


  • 相关阅读:
    [Spark内核] 第38课:BlockManager架构原理、运行流程图和源码解密
    [Spark内核] 第37课:Task执行内幕与结果处理解密
    [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等
    [Spark内核] 第35课:打通 Spark 系统运行内幕机制循环流程
    [Spark性能调优] 第三章 : Spark 2.1.0 中 Sort-Based Shuffle 产生的内幕
    [Spark内核] 第34课:Stage划分和Task最佳位置算法源码彻底解密
    spring boot 日志收集整理
    mybatis 使用redis实现二级缓存(spring boot)
    MD5收集整理
    IntelliJ IDEA 2019.2最新版本免费激活码
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5255338.html
Copyright © 2020-2023  润新知