• C++primer 练习13.39


    13.39 编写你自己版本的StrVec,包括自己版本的reserve,capacity(参见9.4节,第318页)和resize(参见9.3.5节,第314页)

    13.40 为你的StrVec类添加一个构造函数,它接受一个initializer_list<string>参数

    这是StrVec.h

    #pragma once
    
    #include<string>
    #include<memory>
    #include<initializer_list>
    using namespace std;
    
    class StrVec
    {
    public:
        StrVec():
            elements(nullptr),first_free(nullptr),cap(nullptr){}
        StrVec(initializer_list<string> iLStr);//构造函数,接受一个initializer_list<string>参数
        StrVec(const StrVec&);
        StrVec& operator=(const StrVec&);
        ~StrVec();
        string& operator[](size_t n)const //重载下标运算符,用来实现TextQuery和QueryResult对StrVec的使用
        {
            return *(elements + n);
        }
        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; }
        void reserve(size_t n);//分配至少容纳n个元素的空间
        void resize(size_t n);//调整容器的大小为n个元素。若n<size(),则多出的元素被丢弃
                              //若必须添加新元素,对新元素进行值初始化
        void resize(size_t n,string str);//调整容器的大小为n个元素,任何新添加的元素都初始化为值str
    private:
        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;
    };
    
    void StrVec::push_back(const string &s)
    {
        chk_n_alloc();
        alloc.construct(first_free++, s);
    }
    
    pair<string*,string*>
    StrVec::alloc_n_copy(const string  *b, const string *e)
    {
        auto data = alloc.allocate(e - b);
        return{ data,uninitialized_copy(b,e,data) };
    }
    
    void StrVec::free()
    {
        if (elements) {
            for (auto p = first_free;p != elements;)
                alloc.destroy(--p);
            alloc.deallocate(elements, cap - elements);
        }
    }
    
    StrVec::StrVec(const StrVec &s)
    {
        auto newdata = alloc_n_copy(s.begin(), s.end());
        elements = newdata.first;
        first_free = cap = newdata.second;
    }
    
    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;
    }
    
    void StrVec::reallocate()
    {
        auto newcapacity = size() ? 2 * size() : 1;
        auto newdata = alloc.allocate(newcapacity);
        auto dest = newdata;
        auto elem = elements;
        for (size_t i = 0;i != size();++i)
            alloc.construct(dest++, move(*elem++));
        free();
        elements = newdata;
        first_free = dest;
        cap = elements + newcapacity;
    }
    
    void StrVec::reserve(size_t n)//分配至少容纳n个元素的空间
    {
        if (n > capacity())//如果n大于capacity()才会从新分配空间
        {
            auto newdata = alloc.allocate(n);//重新分配n个空间,newdata为新分配的空间的首地址
            auto dest = newdata;  
            auto elem = elements;
            for (;elem != first_free;)       //为新分配的空间调用construct来实现string的构造,采用move调用的是移动构造函数
                alloc.construct(dest++, move(*(elem++)));
            free();                          //元素的移动完成,释放原有的空间
            elements = newdata;              //为指针赋予新的值
            first_free = dest;
            cap = elements + n;
        }
        else return;
    }
    
    void StrVec::resize(size_t n)//调整容器的大小为n个元素。若n<size(),则多出的元素被丢弃
                          //若必须添加新元素,对新元素进行值初始化
    {
        if (n <= size())  //如果n<size()则,应该对n后面的所有已经构造的元素调用destroy(),即多出的元素被丢弃
        {
            for (;first_free != elements + n;)
                alloc.destroy(--first_free);
        }
        else
        {
            if (n > capacity())
            {
                reserve(n);   //因为n>capacity(),所以一定会分配新的空间
            }
            for (;first_free != elements + n;)  //添加新的元素,对新的元素进行值初始化
                alloc.construct(first_free++, string(""));
        }
    }
    
    void StrVec::resize(size_t n,string str)//调整容器的大小为n个元素,任何新添加的元素都初始化为值str
                                 
    {
        if (n <= size())  //如果n<size()则,应该对n后面的所有已经构造的元素调用destroy(),即多出的元素被丢弃
        {
            for (;first_free != elements + n;)
                alloc.destroy(--first_free);
        }
        else
        {
            if (n > capacity())
            {
                reserve(n);   //因为n>capacity(),所以一定会分配新的空间
            }
            for (;first_free != elements + n;)  //添加新的元素为str
                alloc.construct(first_free++, str);
        }
    }
    
    StrVec::StrVec(initializer_list<string> iLStr)//构造函数,接受一个initializer_list<string>参数
    {
        auto newdata = alloc_n_copy(std::begin(iLStr), std::end(iLStr));//调用alloc_n_copy函数,返回一个pair<string*,string*>
        elements = newdata.first;                            //pair的第一个元素为新分配空间的地址
        first_free = cap = newdata.second;                   //pair的第二个元素为新分配空间的最后一个元素之后的地址
    }

    下面是主函数,用来验证程序的正确性

    // 13.5.cpp : 定义控制台应用程序的入口点。
    //
    
    
    #include "stdafx.h"
    #define _SCL_SECURE_NO_WARNINGS
    #include"StrVec.h"
    #include<string>
    #include<iostream>
    #include<memory>
    using namespace std;
    
    int main()
    {
        StrVec sv({ "li","dandan","is" });
        cout << sv.size() << " " << sv.capacity() << endl;
        sv.resize(5, "handsome");
        cout << sv.size() << " " << sv.capacity() << endl;
        sv.resize(3);
        cout << sv.size() << " " << sv.capacity() << endl;
        sv.resize(6);
        cout << sv.size() << " " << sv.capacity() << endl;
        sv.reserve(20);
        sv.push_back("handsome");
        cout << sv.size() << " " << sv.capacity() << endl;
        return 0;
    }
  • 相关阅读:
    tip
    tip
    paper clip 使用
    这个菜单有点cool
    jqueryoptiontree plugin introduce by frederick.mao
    ruby语法不理解
    近来心得,心不可太贪,见好就收
    XPCOM的有关链接
    rails router
    rails3高端observer模式
  • 原文地址:https://www.cnblogs.com/csudanli/p/5388478.html
Copyright © 2020-2023  润新知