std::forward_list

2024-06-16 03:58
文章标签 list std forward

本文主要是介绍std::forward_list,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://classfoo.com/ccby/article/5wWLx

    
  1. // <forward_list>
  2. template < class T, class Alloc = allocator<T> > class forward_list;

正向列表(Forward list)是一个允许在序列中任何一处位置以常量耗时插入或删除元素的顺序容器(Sequence container)。

A forward_list is a container that supports forward iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically.


容性特性:

(1)顺序序列

顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。

(2)单链表

容器中的每个元素保存了定位前一个元素及后一个元素的信息,允许在任何一处位置以常量耗时进行插入或删除操作,但不能进行直接随机访问(Direct random access)。

(3)能够感知内存分配器的(Allocator-aware)

容器使用一个内存分配器对象来动态地处理它的存储需求。


  • 模板参数


                                                                                                      T :存储在容器中的元素的数据类型。在类模板内部,使用其别名为 value_type 的成员类型。

    Alloc  :容器内部用来管理内存分配及释放的内存分配器的类型。

    这个参数是可选的,它的默认值是 std::allocator<T>,这个是一个最简单的非值依赖的(Value-independent)内存分配器。 在类模板内部,使用其别名为 allocator_type 的成员类型。

  • 详细说明

                                                                                                                                                                                                        标准模板库(Standard Template Library,简称STL)中的正向列表容器采用的是单链表(Singly-linked lists)数据库构。单链表可以保存以不同且无关的储存位置容纳的元素。元素间的顺序是通过各个元素中指向下一个元素的链接这一联系维护的。

    该特点跟 std:: list 容器的有点相似:主要的区别就是 std:: list 的元素中不仅保存了指向下一个元素的链接,还保存了指向上一个元素的链接,这使得 std::list 允许双向迭代,但消耗更多的存储空间且在插入删除元素时会有稍高(Slight higher)的耗时。因此 std::forward_list 对象比 std::list 对象更高效,尽管它们只能正向迭代。

    增加或移动正向列表中的元素不会使指向它们的指针、引用、迭代器失效,只有当对应的元素被销毁时才会如此。

    相比较于其它的基本标准顺序容器(数组 std::array、向量 std::vector、双端队列 std::deque 等),正向列表通常在容器中已获得迭代器的任意位置处插入、获得(Extracting,提取)、移动元素等操作中表现出更出色的性能,对那些密集使用上述操作的算法,使用正向列表同样能提升性能,比如排序算法。

    双向链表(std::list)及正向链表(std:: forward_list)相比于其它顺序容器的主要缺点是它们不能够通过元素在容器中的位置直接访问(Direct access)元素。举个例子:如果想访问一个正向列表中的第六个元素,那么就必须从一个已知位置(比如开头或末尾)处开始迭代,这会消耗与两个位置之间距间相关的线性时间。而且它们还为保存各个元素间的链接信息消耗更多额外的内存(这点对由小尺寸元素组成而元素数较大的正向列表尤为明显)。

    Fast random access to list elements is not supported.


    forward_list 类模板是专为极度考虑性能的程序而设计的,它就跟自实现的C型单链表(C-style singly-linked list)一样高效。甚至为了性能,它是唯一一个缺少 size 成员函数的标准容器:这是出于其单链表的性质,如果拥有 size 成员函数,就必须消耗常量时间来维护一个用于保存当前容器大小的内部计数器,这会消耗更多的存储空间,且使得插入及删除操作略微降低性能。如果想获得 forward_list 的大小,可以使用 std::distance 算法且传递 forward_list::begin 及 forward_list::end 参数,该操作的时间复杂度为 O(n)

    对任意列表(std::list)进行插入或删除元素操作需要访问插入位置前的元素,但对 forward_list 来说访问该元素没有常数时间(Constant-time)的方法。因为这个原因,对传递给清除(Erase)、拼接(Splice)等成员函数的范围参数作了修改,这些范围必须为开区间(即不包括末尾元素的同时也不包括起始元素)。

    Modifying any list requires access to the element preceding the first element of interest, but in a forward_list there is no constant-time way to acess a preceding element. For this reason, ranges that are modified, such as those supplied to erase and splice, must be open at the beginning.

  • 成员类型


    成员类型 定义
    value_type 第一个模板参数 T
    allocator_type 第二个模板参数 Alloc
    size_type 无符号整数类型(通常为 size_t
    difference_type 有符号整数类型(通常为 ptrdiff_t
    reference value_type&
    const_reference const value_type&
    pointer std::allocator_traits<Allocator>::pointer
    const_pointer std::allocator_traits<Allocator>::const_pointer
    iterator 正向迭代器
    const_iterator 常正向迭代器
  • 成员函数


    (constructor) 创建 forward_list
    (destructor) 释放 forward_list​
    operator= 值赋操作

    Iterators:

    before_begin 返回指向容器起始位置前的迭代器(iterator
    begin 返回指向容器起始位置的迭代器
    end 返回指向容器末尾下一个位置的迭代器
    cbefore_begin 返回指向容器起始位置前的常迭代器(const_iterator
    cbegin 返回指向容器起始位置的常迭代器
    cend 返回指向容器末尾下一个位置的常迭代器

    Capacity:

    empty 判断是否为空
    max_size 返回 forward_list 支持的最大元素个数

    Element access:

    front 访问第一个元素

    Modifiers

    assign 将新的内容赋值给容器
    emplace_front  在容器开头构造及插入一个元素
    push_front 在容器开头插入一个元素
    pop_front 删除第一个元素
    emplace_after 构造及插入一个元素
    insert_after 插入元素
    erase_after 删除元素
    swap 交换内容
    resize 改变有效元素的个数
    clear 清空内容

    Operations:

    splice_after 使元素从一个正向列表移动到另一个正向列表
    remove 删除值为指定值的元素
    remove_if 删除满足指定条件的元素
    unique 删除重复值
    merge 合并已排序的正向列表
    sort 为容器中的所有元素排序
    reverse 反转元素的顺序

    Observers

    get_allocator 获得内存分配器
  • 非成员函数


    operator==、operator!=、operator<、operator<=、operator>、operator>= 关系操作符
    std::swap 交换两个正向列表的内容
  • 算法相关                                                                           <algorithm> 头文件中包含大量与 forward_list 容器相关的算法

    搜索算法 std::adjacent_findstd::count、
    std::count_ifstd::find、
    std::find_ifstd::find_end、
    std::find_first_ofstd::search、
    std::search_nstd::equal、
    std::mismatch
    二分查找(Binary search) std::lower_boundstd::upper_bound、
    std::equal_rangestd::binary_search
    集合(Set)操作 std::includesstd::set_difference、
    std::set_intersectionstd::set_union、
    std::set_symmetric_difference
    最大与最小 std::min_elementstd::max_element
    字典序比较 std::lexicographical_compare
    排列生成器 std::next_permutation
    std::prev_permutation
    其它操作 std::all_ofstd::any_ofstd::none_of
    std::for_eachstd::copystd::copy_if
    std::copy_nstd::copy_backward
    ​std::movestd::move_backward
    std::swap_rangesstd::iter_swap
    std::transformstd::replace
    std::replace_ifstd::replace_copy
    std::replace_copy_ifstd::fill
    std::fill_nstd::generate
    std::generate_nstd::remove
    std::remove_ifstd::unique
    std::unique_copystd::reverse
    ​std::reverse_copystd::rotate
    std::rotate_copystd::random_shuffle
    std::shufflestd::partition
    std::is_partitionedstd::stable_partition
    std::partition_copystd::merge

    具体内容详见各个功能函数。除了排序(std::sort 等)、堆操作(std::make_heapstd::sort_heap 等)、第n个元素(std::nth_element),适用于 std::vector 的例子基本上都适用于 std::forward_list,可以参考 vector 与算法 主题,该主题包含大量的代码示例。

  • 代码示例

    综合

    下面这个例子简单地介绍了 forward_list 的常用使用方法。

       
    1. #include <iostream>
    2. #include <forward_list>
    3. #include <numeric>
    4. #include <algorithm>
    5. namespace ClassFoo{
    6. using namespace std;
    7.  
    8. void ForwardListExample1(){
    9. forward_list<int> foo1;
    10. forward_list<int>::iterator it;
    11. //从前面向foo1容器中添加数据
    12. foo1.push_front (2);
    13. foo1.push_front (1);
    14. foo1.push_front (14);
    15. foo1.push_front (17);
    16. //按从小到大排序
    17. foo1.sort();
    18. cout<<"foo1中的元素"<<endl;
    19. for (it = foo1.begin(); it != foo1.end(); ++it)
    20. cout << *it << " ";
    21. cout << endl;
    22. //使用STL的accumulate(累加)算法
    23. int result = accumulate(foo1.begin(), foo1.end(),0);
    24. cout<<"和为:"<<result<<endl;
    25. //使用STL的max_element算法求foo2中的最大元素并显示
    26. it=max_element(foo1.begin(),foo1.end());
    27. cout << "最大元素是: "<< *it <<endl;
    28. }
    29. }
    30. int main()
    31. {
    32. ClassFoo::ForwardListExample1();
    33. return 0;
    34. }

    输出

    foo1中的元素
    1 2 14 17
    和为:34
    最大元素是: 17

    一个有用的宏

    虽然 C++11 中已经开始支持初始化列表,但可能您的编译器还未支持(即使已经支持 C++11),此时,可以使用如下等效的解决方案。

       
    1. #define CLASSFOO_FORWARD_LIST(type, name, ...) \
    2. static const type name##_a[] = __VA_ARGS__; \
    3. std::forward_list<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

    可以这样使用:

       
    1. CLASSFOO_FORWARD_LIST(int,foo,{1,2,3,4,5,6,7});

     



这篇关于std::forward_list的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1065407

相关文章

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

【Python报错已解决】AttributeError: ‘list‘ object has no attribute ‘text‘

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一:检查属性名2.2 步骤二:访问列表元素的属性 三、其他解决方法四、总结 前言 在Python编程中,属性错误(At

List list = new ArrayList();和ArrayList list=new ArrayList();的区别?

List是一个接口,而ArrayList 是一个类。 ArrayList 继承并实现了List。 List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了A

处理List采用并行流处理时,通过ForkJoinPool来控制并行度失控的问题

在使用parallelStream进行处理list时,如不指定线程池,默认的并行度采用cpu核数进行并行,这里采用ForJoinPool来控制,但循环中使用了redis获取key时,出现失控。具体上代码。 @RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)@Slf4jpublic class Fo

Java中集合类Set、List和Map的区别

Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。那么它们有什么区别呢? Set中的对象不按特定方式排序,并且没有重复对象。但它的有些实现类能对集合中的对

List对象过滤

List materialInventoryList = materialInventories.stream().filter(mat -> mat.getQty().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList()); stream().filter()方法可以过滤掉List的数据

c++stack和list 介绍

stack介绍 堆栈是一种容器适配器,专门设计用于在 LIFO 上下文(后进先出)中运行,其中元素仅从容器的一端插入和提取。 堆栈作为容器适配器实现,容器适配器是使用特定容器类的封装对象作为其基础容器 的类,提供一组特定的成员函数来访问其元素。元素从特定容器的 “back” 推送或弹出,这称为堆栈的顶部。 stack接口 stack() 构造空的栈 empty() 检测stack是否为

C++——list的实现

目录 0.前言 1.节点类  2.迭代器类  ①普通迭代器 ②const迭代器  ③模板迭代器 3.list类  3.1 clear、析构函数、swap ①clear ② 析构函数  ③ swap 3.2构造函数  ①无参构造  ②赋值构造 3.3 迭代器 3.4插入函数 ①insert插入 ②头插 ③尾插 3.5 删除函数 ①erase删除 ②头删