zoukankan      html  css  js  c++  java
  • 动态内存管理类

    内存管理类需要包括以下几个基本操作的正确性

    1. 添加元素:判断管理的空间大小是否能够添加新元素,如不够,则使用allocator分配内存,并将旧数据移动到新内存,然后释放旧内存,并更新内存首指针、第一个可用内存指针、尾指针位置。
    2. 对象拷贝:使用allocator的allocate分配内存,相关的uninitialized_copy拷贝元素到新的位置,并更新内存首指针、第一个可用内存指针、尾指针位置。
    3. 内存释放:使用allocator的destroy销毁内存,并使用deallocate执行内存回收操作

    注意:静态对象必须首先在类外进行初始化操作。

    //uninitialized_copy被编译器认为是不安全的,这语句是让编译器停止警告,放到第一行
    #pragma warning(disable : 4996)
    #include<iostream>
    #include<string>
    #include<memory>
    using namespace std;
    class StrVec
    {
    public:
        StrVec() :
            elements(nullptr), first_free(nullptr), cap(nullptr)
        {
        }
        //拷贝构造函数
        StrVec(const StrVec& s)
        {
            auto newdata = alloc_n_copy(s.begin(), s.end());
            elements = newdata.first;
            first_free = cap = newdata.second;
        }
        //拷贝赋值运算
        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;
        }
        //析构函数
        ~StrVec() { free(); }
        //添加对象函数
        void push_back(const string& str)
        {
            chk_n_alloc();
            //在first_free位置构造元素
            alloc.construct(first_free++, str);
        }
        //输出内容
        void print(ostream& os)
        {
            for (auto pos = begin(); pos != end(); pos++)
                os << *pos << endl;
        }
        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:
        static allocator<string> alloc;
        void chk_n_alloc()
        {
            if (size() == capacity()) 
                reallocate();
        }
        //工具函数,被拷贝构造函数、赋值运算符和析构函数使用
        std::pair<string*, string*>alloc_n_copy(const string*b, const string*e)
        {
            auto data = alloc.allocate(e - b);
            return{ data,uninitialized_copy(b,e,data) };
        }
        //销毁元素,释放内存
        void free()
        {
            //不能传递给一个空指针,为0什么也不做
            if (elements)
            {
                for (auto p = first_free; p != elements;)
                    alloc.destroy(--p);
                alloc.deallocate(elements, cap - elements);
            }
        }
        //获得更多内存,拷贝已有元素
        void 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++)
                //移动的时候,通过move函数转换为右值引用,使用了移动构造函数构造对象
                alloc.construct(dest++, std::move(*elem++));
            free();//移动完成,释放旧内存
            //更新数据结构,换到新元素
            elements = newdata;
            first_free = dest;
            cap = elements + newcapacity;
        }
        //指向数组首元素指针
        string *elements;
        //指向数组第一个空闲元素的指针
        string *first_free;
        //指向数组尾后位置
        string *cap;
    };
    allocator<string> StrVec::alloc;

    使用时

    int main()
    {
        {
            StrVec strVec;
            strVec.push_back("asdfasdf");
            //strVec.push_back("123456");
            //strVec.push_back("!@#$%^&");
            //strVec.push_back("123123!@#$%^&");
            auto strVec1 = strVec;
            strVec1.push_back("!@#$%^&");
            strVec.print(cout);
            strVec1.print(cout);
        }
        _CrtDumpMemoryLeaks();
    }
  • 相关阅读:
    HDU 1097 a hard puzzle
    HDU 4588 Count The Carries
    不想用锐捷怎么办?锐捷出问题|锐捷不能用怎么办?用menohust代替吧
    线段树及其变种的相关资料(不定期更新)
    UVa 10075
    UVa 1301
    UVa 10256
    UVa 1453
    计算几何相关资料+题目推荐(不定期补充)
    UVa 11524
  • 原文地址:https://www.cnblogs.com/qiusuo/p/5100281.html
Copyright © 2011-2022 走看看