zoukankan      html  css  js  c++  java
  • C++ 空间配置器allocator类

    allocator类

    C++中,内存分配和对象构造紧密纠缠(new),就像对象析构和回收一样(delete)。如果程序员想接管内存分配,即将内存分配和对象构造分开,对于前者,主要是分配和释放未构造的原始内存;对于后者,主要是在原始内存中构造和撤销对象。

    分配和释放未构造的原始内存 两种方法:

    • allocator类,提供可感知类型的内存分配;
    • 标准库中的opeator new和operator delete,它们分配和释放需要大小的原始、未类型化的内存;

    在原始内存中构造和撤销对象 不同方法:

    • allocator类定义了名为construct和destroy的成员;
    • placement new表达式,接受指向未构造内存的指针;
    • 直接调用对象的析构函数来撤销对象;
    • 算法uninitialized_fill 和 uninitialized_copy,在目的地构造对象;

    C++的STL中定义了很多容器,容器的第二个模板参数通常为allocator类型,标准库中allocator类定义在头文件memory中,用于帮助将内存分配和对象的构造分离开来。它分配的内存是原始的、未构造的。

    表达式 说明
    allocator<T> a  定义了一个名为a的allocator对象,它可以为类型T的对象分配内存
    a.allocator(n)  分配一段原始的、未构造的内存,这段内存能保存n个类型为T的对象
    a.deallocate(p, n)

    释放T*指针p地址开始的内存,这块内存保存了n个类型为T的对象,p必须是一个先前由allocate返回的指针,

    且n必须是p创建时所要求的大小,且在调用该函数之前必须销毁在这片内存上创建的对象。

    a.construct(p, t) 在T*指针p所指向内存中构造一个新元素。运行T类型的复制构造函数用t初始化该对象
    a.destory(p)  运行T*指针p所指向对象的析构函数
       
    uninitialized_copy(b,e,b2)

    从迭代器b和e指出的输入范围中拷贝元素到从迭代器b2开始的未构造的原始内存中,该函数在目的地构造元素,而不是给它们复制。

    假定由b2指出的目的地足以保存输入范围中元素的副本

    uninitialized_fill(b,e,t)  将由迭代器b和e指出的范围中的对象初始化为t的副本,假定该范围是未构造的原始内存,使用复制构造函数构造对象
    uninitalized_fiil_n(b,e,t,n) 将由迭代器b和e指出的范围中至多n个对象初始化为t的副本,假定范围至少为n个元素大小,使用复制构造函数构造对象

          

          
        STL都会使用allocator类来为容器分配空间,例如:

    #include <memory>
    
    template <class T> class Vector {
        public:
            Vector(): elements(0), first_free(0), end(0) {}
            void push_back(const T&);
    
        private:
            static std::allocator<T> alloc; // object to get raw memory
            void reallocate();  // get more space and copy existing elements
            T* elements;        // pointer to first elment in the array
            T* first_free;      // pointer to first free element in the array
            T* end;             // pointer to one past the end of the array
    };
    
    template <class T> std::allocator<T> Vector<T>::alloc;
    
    template <class T>
    void Vector<T>::push_back(const T& t) {
        if (first_free == end) {
            reallocate(); 
        }   
        alloc.construct(first_free, t); 
        first_free++;
    }
    
    template <class T>
    void Vector<T>::reallocate() {
        // compute size of current array and allocate space for twice as many elements
        std::ptrdiff_t size = first_free - elements;
        std::ptrdiff_t newcapacity = 2 * (size > 1 ? size : 1); 
        T* newelements = alloc.allocate(newcapacity);
    
        std::uninitialized_copy(elements, first_free, newelements);
    
        for (T* p = first_free; p != elements; alloc.destroy(--p));
    
        if (elements) {
            alloc.deallocate(elements, end - elements);
        }
    
        elements = newelements;
        first_free = elements + size;
        end = elements + newcapacity;
    }

          

       

                  

                 

  • 相关阅读:
    RAID磁盘阵列介绍
    Nginx如何使用Nginx实现MySQL数据库的负载均衡
    挽救数据库性能的30条黄金法则
    mysql主从复制 (指定复制的数库或者表)
    Nginx系列之负载均衡策略
    Redis安装部署(一主二从三哨兵)
    让你的 Linux 命令骚起来
    MySQL/数据库 知识点总结
    Docker私有仓库搭建与界面化管理
    mysql sql语句修改字段名称,字段长度
  • 原文地址:https://www.cnblogs.com/chenny7/p/12255961.html
Copyright © 2011-2022 走看看