c++17内存池与多态分配器std::pmr::memory_resource

  • list用法
    • splice(迭代器位置,容器):把容器中的所有元素移动到指定迭代器的指定位置
      std::list<int> ls1;
      std::list<int> ls2;
      for (size_t i = 0; i < 3; i++)
      {
          ls1.push_back(i);//0 1 2
          ls2.push_back(i+10);//10 11 12
      }    
      ls1.splice(ls2.begin(), ls1);
      //ls1.splice(ls2.begin(), ls1, ++ls1.begin());//将1移动到ls2的起始位置
      //此时ls2中为0 1 2 10 11 12,而ls1为空
      for(auto l:ls2)
      {
          std::cout<<l<<std::endl;//0 1 2 10 11 12
      }
      
    • unique去重相邻重复元素
      ls1.unique();
  • std::sort原理

    原理:主要采用快速排序,但是快速排序如果枢纽没选好,会导致递归深度很大,为了避免这种情况,当递归深度达到一定次数,就不会继续递归下去了,而是转用堆排序。当元素个数小于等于16了,也不再使用快速排序,而是直接使用插入排序。
    实现:sort 传入2个迭代器对象(左闭右开)和一个比较函数(默认升序),首先调用上述的混合排序函数__introsort_loop(__first, __last, 栈深, __comp),这个函数内有个while循环,当元素个数小于等于16才会退出。最后调用插入排序的函数。
    由于std::sort要求容器支持RandomAccessIterator接口,也就是支持通过下标随机访问各元素,但list的迭代器只支持双向访问,不支持随机访问。因此,不能调用std::sort来排序,而是使用容器自身的sort来排序。

  • list的push_back比vector慢很多

    因为节点是分配在堆上的,每增加一个节点,就要malloc一次节点,并填充左右指针

  • 自定义容器的内存分配方式:这里提前申请好一块内存,相当于缓冲池,避免了list每次新增节点时都要malloc一次
    #include <iostream>
    #include <list>
    static char g_buf[65535*120];
    //专门写一个结构体存储分配的数据,作为缓冲区,而不是写在分配器里
    struct my_memory_resource
    {
        char *m_buf = g_buf;
        size_t m_watermark = 0;//记录已分配内存大小
        char* do_allocate(size_t n)//把分配内存的函数也写在这里,而不是分配器里
        {
            char *p = m_buf + m_watermark;
            m_watermark += n;
            return p;
        }
    };
    
    //自定义容器的内存分配器,因为容器是调用allocate来分配内存
    template<class T>
    struct my_custom_allocator{
        my_memory_resource *m_resource{};
        using value_type = T;
        //构造函数:这里对缓冲区进行初始化
        my_custom_allocator(my_memory_resource * resource):m_resource(resource){};
        T *allocate(size_t n)
        {
            char *p = m_resource->do_allocate(n*sizeof(T), alignof(T));//不对齐内存访问会产生未定义行为
            return (T*)p;
        }
        void deallocate(T *p, size_t n)
        {
            //什么都不做
        }
        my_custom_allocator() = default;
        template<class U>
        constexpr my_custom_allocator(my_custom_allocator<U> const &other) noexcept:m_resource(other.m_resource){
        }
        constexpr bool operator==(my_custom_allocator const &other) const noexcept{
            return m_resource == other.m_resource;
        }
    };
    
    int main() {
        my_memory_resource mem;
        std::list<char, my_custom_allocator<char>> a(12,my_custom_allocator<char>(&mem));
        for (int i = 0; i < 65535; i++)
        {
            a.push_back(12);
        }
        return 0;
    }
    
  • c++17提供了上述分配器的多态版(do_allocate写成虚函数实现的)

    分配器std::pmr::polymorphic_allocator
    缓冲池:memory_resource是一个抽象类,其有具体的实现函数,不要直接使用memory_resource。实现函数有:monotonic_buffer_resource,在使用时只能作为局部变量,否则会因为其deallocate什么都没做而导致内存一直涨。如果需要作为全局变量,那么使用unsynchronized_pool_resource或synchronized_pool_resource(区别是后者可以在多线程中使用)

    #include <iostream>
    #include <list>
    #include <memory_resource>
    int main() {
        std::pmr::monotonic_buffer_resource mem;
        std::list<char,std::pmr::polymorphic_allocator<char>> a(12,&mem);//这里&mem发生了隐式类型转换
        //也可以简写为std::pmr::list<char> a(&mem);
        for (int i = 0; i < 65535; i++)
        {
            a.push_back(12);
        }
        return 0;
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The C++ language has a long history, dating back to the 1980s. Recently it has undergone a renaissance, with major new features being intro duced in 2011 and 2014. At press time, the C++17 standard is just around the corner. C++11 practically doubled the size of the standard library, adding such headers as , , and . C++17 doubles the library again, with additions such as , , and . A programmer who’s been spending time writing code instead of watching the standardization process might fairly feel that the standard library has gotten away fromhim--that there’s so many new things in the library that he'll never be able to master the whole thing, or even to sort the wheat fromthe chaff. After all, who wants to spend a month reading technical documentation on std::locale and std::ratio , just to find out that they aren't useful in your daily work? In this book, I'll teach you the most important features of the C++17 standard library. In the interest of brevity, I omit some parts, such as the aforementioned ; but we'll cover the entire modern STL (every standard container and every standard algorithm), plus such imp ortant topics as smart pointers, randomnumbers, regular expressions, and the new-in-C++17 library. I'll teach by example. You'll learn to build your own iterator type; your own memory allocator using std::pmr::memory_resource ; your own thread pool using std::future . I'll teach concepts beyond what you'd find in a reference manual. You'll learn the difference between monomorphic, polymorphic, and generic algorithms (Chapter 1 , Classical Polymorphism and Generic Programming ); what it means for std::string or std::any to be termed a "vocabulary type"(Chapter 5 , Vocabulary Types ); and what we might expect fromfuture C++ standards in 2020 and beyond. I assume that you are already reasonably familiar with the core language of C++11; for example, that you already understand how to write class and function templates, the difference between lvalue and rvalue references, and so on.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值