- 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();
- splice(迭代器位置,容器):把容器中的所有元素移动到指定迭代器的指定位置
- 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; }
c++17内存池与多态分配器std::pmr::memory_resource
最新推荐文章于 2025-04-01 00:00:00 发布