C++的forward_list

参考:

http://blog.csdn.net/devourheavens/article/details/7497172

http://zh.cppreference.com/w/cpp/container/forward_list

forward_list

<forward_list>

template < class T, class Alloc = allocator<T> > class forward_list;

Forward list

        前向链表是序列容器,使固定时间插入和擦除操作序列内的任何地方。

前向链表的实现方式和单链表相同;单链表可以存储所包含的每个元素在不同的和无关的存储位置。

在序列中顺序保存每个元素指向下一个元素的关联。

         forward_list容器与list容器的主要设计区别是list保持内部唯一的一个链接到下一个元素,而后者则保持每个元素的两个链接:一个指向下一个元素和一个前一个。允许高效在两个方向迭代,但每个元素的消耗额外的存储空间,并轻微较高的时间开销插入和删除元素的迭代。forward_list对象,从而比list对象更有效率,虽然他们只能向前遍历。

           与其他的基本标准序列容器(array,vector和deque)相比,forward_list一般在容器内的任何位置中的元素的插入、提取和移动操作效率更高,因此在算法中较密集的使用这些操作,例如排序算法。

          相比其他序列容器,forward_lists的主要缺点是缺乏直接访问他们的位置的元素,例如,要进入第六个元素在forward_list的一个遍历从一开始就到那个位置,这需要线性时间之间的距离。他们也消耗了一些额外的内存保持连接信息相关联的每个元素(这可能是一个小型的元素的大链表的重要因素)。

          考虑到forward_list类模板设计的性能:根据设计,它是作为一个简单的手写C风格的单链表一样高效,实际上是仅有的一个标准容器故意缺乏其大小的成员函数是出于效率的考虑。由于其作为一个链表的性质,有一个大小成员在固定的时间,需要保持一个内部的计数器保存其大小(和链表一样)。这会消耗一些额外的存储和使插入和删除操作,效率较低。为了获得一个forward_list对象的大小,可以用其开始和结束,这是一个线性时间的操作距离算法。

容器属性

  序列

         在一个严格的线性序列中序列容器的元素是有序的。个别元素的访问是通过他们在这个序列中的位置。

  链表

      每个元素保持如何找到下一个元素的信息,允许常量时间在特定元素(甚至整个范围)后进行插入和擦除操作,但没有直接随机存取。  

  分配器的获取

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

 

1、成员函数

(构造函数)
构造 forward_list (公开成员函数)
explicit forward_listconst Allocator& alloc = Allocator();
(C++11 起) 
(C++14 前)
forward_list(: forward_list( Allocator({}
explicit forward_listconst Allocator& alloc );
(C++14 起)
forward_list( size_type count, 

              const T& value,

              const Allocator& alloc = Allocator());
(2) (C++11 起)
  (3)  
explicit forward_list( size_type count );
(C++11 起) 
(C++14 前)
explicit forward_list( size_type count, const Allocator& alloc = Allocator();
(C++14 起)
templateclass InputIt >

forward_list( InputIt first, InputIt last, 

              const Allocator& alloc = Allocator();
(4) (C++11 起)
forward_listconst forward_list& other );
(5) (C++11 起)
forward_listconst forward_list& other, const Allocator& alloc );
(5) (C++11 起)
forward_list( forward_list&& other );
(6) (C++11 起)
forward_list( forward_list&& other, const Allocator& alloc );
(7) (C++11 起)
forward_liststd::initializer_list<T> init, 
              const Allocator& alloc = Allocator();
(8) (C++11 起)
     

从各种数据源构造新容器,可选地使用用户提供的分配器 alloc 。

1) 默认构造函数。构造空容器。
2) 构造拥有  count 个有值  value 的元素的容器。
3) 构造拥有个  count  默认插入的  T 实例的容器。不进行复制。
4) 构造拥有范围  [first, last) 内容的容器。
若 InputIt 是整数类型,则此构造函数拥有的效果同 forward_list(static_cast<size_type>(first), static_cast<value_type>(last), a) 。 (C++11 前)
此重载仅若InputIt 满足 输入迭代器 (InputIterator) 才参与重载决议,以避免和重载 (2) 的歧义。 (C++11 起)
5) 复制构造函数。构造拥有  other 内容的容器。若不提供  alloc ,则如同通过调用  std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator()) 获得分配器。
6) 移动构造函数。用移动语义构造拥有  other 内容的容器。分配器通过属于  other 的分配器移动构造获得。
7) 有分配器扩展的移动构造函数。将  alloc 用作新容器的分配器,从  other 移动内容;若  alloc != other.get_allocator() ,则它导致逐元素移动。
8) 构造拥有 initializer_list  init 内容的容器。

参数

alloc - 用于此容器所有内存分配的分配器
count - 容器的大小
value - 以之初始化容器元素的值
first, last - 复制元素的来源范围
other - 用作初始化容器元素来源的另一容器
init - 用作初始化元素来源的 initializer_list

复杂度

1) 常数
2-3) 与  count 成线性
4) 与  first 和  last 的距离成线性
5) 与  other 的大小成线性
6) 常数。
7) 若  alloc != other.get_allocator() 则为线性,否则为常数。
8) 与  init 的大小成线性。

异常

到 Allocator::allocate 的调用可能抛出。

注意

在容器移动构造(重载 (6) )后,指向 other 的引用及迭代器(除了尾迭代器)保持合法,但指代现于 *this 中的元素。

(析构函数)
析构 forward_list (公开成员函数)
     
     
   
   
     
     
operator=
赋值给容器 (公开成员函数)
forward_list& operator=const forward_list& other );
(1) (C++11 起)
  (2)  
forward_list& operator=( forward_list&& other );
(C++11 起) 
(C++17 前)
forward_list& operator=( forward_list&& other noexcept(/* see below */);
(C++17 起)
forward_list& operator=std::initializer_list<T> ilist );
(3) (C++11 起)
     

替换容器内容。

1) 复制赋值运算符。以  other 的副本替换内容。 若 std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value 为 true ,则以源分配器的副本替换目标分配器。若源分配器与目标分配器不比较相等,则用目标( *this )分配器销毁内存,然后在复制元素前用 other 的分配器分配。 (C++11 起).、
2) 移动赋值运算符。用移动语义以  other 的内容替换内容(即从  other 移动  other 中的数据到此容器)。之后  other 在合法但未指定的状态。若  std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value 为  true ,则用源分配器的副本替换目标分配器。若它为  false 且源与目标分配器不比较相等,则目标不能取走源内存的所有权,而必须单独移动赋值逐个元素,用自己的分配器按需分配额外的内存。任何情况下,原先在  *this 中的元素要么被销毁,要么以逐元素移动赋值替换。
3) 以 initializer_list  ilist 所标识者替换内容。

参数

other - 用作数据源的另一容器
ilist - 用作数据源的 initializer_list

返回值

*this

复杂度

1) 与  *this 和  other 的大小成线性。
2) 与  *this 的大小成线性,除非分配器不比较相等且不传播,该情况下与  *this 和  other 的大小成线性。
3) 与  *this 和  ilist 的大小成线性。

异常

2)  
noexcept 规定:  
noexcept(std::allocator_traits<Allocator>::is_always_equal::value)
(C++17 起)

注意

容器移动赋值(重载 (2) )后,除非不兼容的分配器强制逐元素赋值,否则指向 other 的引用、指针和迭代器(除了尾迭代器)都保持合法,不过指代的元素现在在 *this 中。

   
将值赋给容器 (公开成员函数)
void assign( size_type count, const T& value );
(1) (C++11 起)
templateclass InputIt >
void assign( InputIt first, InputIt last );
(2) (C++11 起)
void assignstd::initializer_list<T> ilist );
(3) (C++11 起)
     

替换容器的内容。

1) 以  count 份  value 的副本替换内容。
2) 以范围  [first, last) 中元素的副本替换内容
若 InputIt 为整数类型,则此重载与 (1) 拥有相同效果。 (C++11 前)
此重载仅若 InputIt 满足输入迭代器 (InputIterator) 才参与重载决议。 (C++11 起)
3) 以来自 initializer_list  ilist 的元素替换内容。

所有指向容器元素的迭代器、指针及引用均被非法化。

参数

count - 容器的新大小
value - 用以初始化容器元素的值
first, last - 复制来源元素的范围
ilist - 复制值来源的 initializer_list

复杂度

1) 与  count 成线性
2) 与  first 和  last 间的距离成线性
3) 与  ilist.size() 成线性
   
返回相关的分配器 (公开成员函数)
allocator_type get_allocator(const;
  (C++11 起)
     

返回与容器关联的分配器。

参数

(无)

返回值

关联的分配器。

复杂度

常数。

 

example

 1 #include<iostream>
 2 #include<string>
 3 #include<forward_list>
 4  
 5 using namespace std;
 6  
 7 //队列重载<<
 8 template<typename T>
 9 ostream& operator<<(ostream& s, const forward_list<T>& v)
10 {
11     s.put('[');
12     char comma[3] = { '\0', ' ', '\0' };
13     for (const auto& e : v) {
14         s << comma << e;
15         comma[0] = ',';
16     }
17     return s << ']';
18 }
19  
20 int main()
21 {
22     forward_list<int>lst{1,2,3,4,5,6};
23  
24     cout << "lst:" << lst << endl;
25  
26     forward_list<int>lst1(lst.begin(), lst.end());
27     cout << "lst1:" << lst1 << endl;
28  
29     //复制构造
30     forward_list<int>lst2(lst);
31     cout << "lst2:" << lst2 << endl;
32  
33     forward_list<string>lst3(5, "AB");
34     cout << "lst3:" << lst3 << endl;
35  
36     forward_list<int>num1{ 1, 2, 3, 4, 5, 6 };
37     forward_list<int>num2;
38     forward_list<int>num3;
39  
40  
41     cout << "num1:" << num1 << endl;
42     // 复制赋值会从 nums1 复制数据到 nums2
43     num2 = num1;
44     cout << "num2:" << num2 << endl;
45  
46     // 移动赋值会从 nums1 移动数据到 nums3 
47     num3 = move(num2);
48     cout << "num3:" << num3 << endl;
49  
50     forward_list<char>ch;
51     ch.assign(6, '*');
52     cout << "ch:" << ch << endl;
53  
54     //重新初始化对象
55     num1.assign(2, 6);
56     cout << "num1:" << num1 << endl;
57  
58     //
59     forward_list<char>ch1;
60     ch1.assign(ch.begin(), ch.end());
61     cout << "ch1:" << ch1 << endl;
62  
63     forward_list<int> mylst;
64     int * p;
65     unsigned int i;
66  
67     //分配数组5个元素的空间用于deque分配器
68     p = mylst.get_allocator().allocate(5);
69  
70     // 空间中赋值
71     for (i = 0; i<5; i++)
72         mylst.get_allocator().construct(&p[i], i);
73  
74     cout << "The allocated array contains:";
75     for (i = 0; i<5; i++) 
76         cout << ' ' << p[i];
77     cout << '\n';
78  
79     // 销毁空间
80     for (i = 0; i<5; i++)
81         mylst.get_allocator().destroy(&p[i]);
82     lst.get_allocator().deallocate(p, 5);
83  
84  
85     system("pause");
86     return 0;
87 }

2、元素访问

元素访问
front
访问第一个元素 (公开成员函数)
reference front();
  (C++11 起)
const_reference front(const;
  (C++11 起)
     

返回到容器首元素的引用。

在空容器上对 front 的调用是未定义的。

参数

(无)

返回值

到首元素的引用

复杂度

常数

注意

对于容器 c ,表达式 c.front() 等价于 *c.begin() 。

 

 

注意无operator[ ] 、at、 back、函数 

3、迭代器

迭代器
before_begin
cbefore_begin
返回指向第一个元素之前迭代器 (公开成员函数)
iterator before_begin(noexcept;
  (C++11 起)
const_iterator before_begin(const noexcept;
  (C++11 起)
const_iterator cbefore_begin(const noexcept;
  (C++11 起)
     

返回指向首元素前一元素的迭代器。此元素表现为占位符,试图访问它会导致未定义行为。仅有的使用情况是在函数 insert_after() 、 emplace_after() 、 erase_after() 、 splice_after() 和迭代器自增中:自增始前迭代器准确地给出与从 begin()/cbegin() 获得者相同的迭代器。

参数

(无)

返回值

指向首元素前一元素的迭代器。

复杂度

常数。

begin
cbegin
 
 
返回指向容器第一个元素的迭代器 (公开成员函数)
iterator begin(noexcept;
  (C++11 起)
const_iterator begin(const noexcept;
  (C++11 起)
const_iterator cbegin(const noexcept;
  (C++11 起)
     

返回指向容器首元素的迭代器。

若容器为空,则返回的迭代将等于 end() 。

range-begin-end.svg

参数

(无)

返回值

指向首元素的迭代器

复杂度

常数

end 
cend
 
 
返回指向容器尾端的迭代器 (公开成员函数)
iterator end(noexcept;
  (C++11 起)
const_iterator end(const noexcept;
  (C++11 起)
const_iterator cend(const noexcept;
  (C++11 起)
     

返回指向后随容器最后元素的元素的迭代器。

此元素表现为占位符;试图访问它导致未定义行为。

range-begin-end.svg

参数

(无)

返回值

指向后随最后元素的迭代器。

复杂度

常数。

 example

 1 #include<iostream>
 2 #include<string>
 3 #include<forward_list>
 4  
 5 using namespace std;
 6  
 7 int main()
 8 {
 9     forward_list<string>str{"aba","asd","sdf","efs","efs","www"};
10  
11     //迭代器
12     forward_list<string>::iterator iter = str.begin();
13     for (; iter != str.end();)
14     {
15         cout << *iter++ << ' ';
16     }
17     cout << endl;
18  
19     //常迭代器
20     forward_list<string>::const_iterator iter1 = str.begin();
21     for (; iter1 != str.end();)
22     {
23         cout << *iter1++ << ' ';
24     }
25     cout << endl;
26  
27     //返回指向首元素前一元素的迭代器
28  
29     str.insert_after(str.before_begin(), "66666");
30     cout <<str.front()<< endl;
31  
32     system("pause");
33     return 0;
34 }

 

4、容量

容量
empty
检查容器是否为空 (公开成员函数)
bool empty(const noexcept;
  (C++11 起) 
(C++20 前)
[[nodiscard]bool empty(const noexcept;
  (C++20 起)
     

检查容器是否无元素,即是否 begin(== end() 。

参数

(无)

返回值

若容器为空则为 true ,否则为 false

复杂度

常数。

max_size
返回可容纳的最大元素数 (公开成员函数)
size_type max_size(const noexcept;
  (C++11 起)
     

返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。

参数

(无)

返回值

元素数量的最大值。

复杂度

常数。

注意

此值典型地反映容器大小上的理论极限。运行时,容器的大小可能被可用 RAM 总量限制到小于 max_size() 的值。

 example

 1 #include<iostream>
 2 #include<forward_list>
 3 #include<ctime>
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     srand(time(0));
 9     forward_list<char> ch{'a','b','c','d','e','f'};
10     
11  
12  
13     if (ch.empty() == 0)
14         cout << "ch is null" << endl;
15  
16     ch.resize(20);
17     //容器可保有的元素最大数量
18     cout << "ch max_size:" << ch.max_size() << endl;
19  
20  
21     system("pause");
22     return 0;
23 }

 

5、修改器

修改器
clear
清除内容 (公开成员函数)
void clear(noexcept;
  (C++11 起)
     

从容器移除所有元素。

非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器保持合法。

参数

(无)

返回值

(无)

复杂度

与容器大小,即元素数成线性。

insert_after
在某个元素后插入新元素 (公开成员函数)
iterator insert_after( const_iterator pos, const T& value );
(1) (C++11 起)
iterator insert_after( const_iterator pos, T&& value );
(2) (C++11 起)
iterator insert_after( const_iterator pos, size_type count, const T& value );
(3) (C++11 起)
templateclass InputIt >
iterator insert_after( const_iterator pos, InputIt first, InputIt last );
(4) (C++11 起)
iterator insert_after( const_iterator pos, std::initializer_list<T> ilist );
(5) (C++11 起)
     

在容器中的指定位置后插入元素。

1-2) 在  pos 所指向的元素后插入  value
3) 在  pos 所指向的元素后插入  value 的  count 个副本
4) 在  pos 所指向的元素后插入来自范围  [first, last) 的元素。 若  first 与  last 是指向  *this 中的迭代器则行为未定义。
5) 插入来自 initializer_list  ilist 的元素。

没有引用和迭代器被非法化。

参数

pos - 内容将插入到其后的迭代器
value - 要插入的元素值
count - 要插入的副本数
first, last - 要插入的元素范围
ilist - 插入值来源的 initializer_list
类型要求
 
 InputIt 必须满足 InputIterator 的要求。

返回值

1-2) 指向被插入元素的迭代器。、
3) 指向最后被插入元素的迭代器,或若  count==0 则为  pos 。
4) 指向最后被插入元素的迭代器,或若  first==last 则为  pos 。
5) 指向最后被插入元素的迭代器,或若  ilist 为空则为  pos 。

异常

若在 insert_after 期间抛出异常,则无效果(强异常保证)。

复杂度

1-2) 常数。
3) 与  count 成线性
4) 与  std::distance(first, last) 成线性
5) 与  ilist.size() 成线性
emplace_after
在元素后原位构造元素 (公开成员函数)
templateclass... Args 
iterator emplace_after( const_iterator pos, Args&&... args );
  (C++11 起)
     

在容器中的指定位置后插入新元素。原位构造元素,即不进行复制或移动操作。准确地以与提供给函数者相同的参数调用元素的构造函数。

没有引用和迭代器被非法化。

参数

pos - 新元素将构造于其后的迭代器
args - 转发给元素构造函数的参数

返回值

指向新元素的迭代器。

复杂度

常数。

异常

若抛出任何异常(例如由构造函数),则容器留在未修改状态,如同从未调用过此函数(强异常保证)。

参阅

erase_after
擦除元素后的元素 (公开成员函数)
iterator erase_after( const_iterator pos );
(1) (C++11 起)
iterator erase_after( const_iterator first, const_iterator last );
(2) (C++11 起)
     

从容器移除指定元素。

1) 移除后随  pos 的元素。
2) 移除范围  (first; last) 中的元素。

参数

pos - 指向前趋要被移除元素的迭代器
first, last - 要移除的元素范围

返回值

1) 指向后随被擦除元素的迭代器,或若不存在这种元素则为  end() 。
2)  last

复杂度

1) 常数。
2) 与  first 和  last 之间的距离成线性。
push_front
插入元素到容器起始 (公开成员函数)
void push_frontconst T& value );
  (C++11 起)
void push_front( T&& value );
  (C++11 起)
     

前附给定元素 value 到容器起始。

没有引用和迭代器被非法化。

参数

value - 要前附的元素值

返回值

(无)

复杂度

常数。

异常

若抛出异常,则此函数无效果(强异常保证)。

emplace_front
在容器头部就地构造元素 (公开成员函数)
templateclass... Args >
void emplace_front( Args&&... args );
  (C++11 起) 
(C++17 前)
templateclass... Args >
reference emplace_front( Args&&... args );
  (C++17 起)
     

插入新元素到容器起始。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args... 作为 std::forward<Args>(args)... 转发给构造函数。

没有引用和迭代器被非法化。

参数

args - 转发给元素构造函数的参数
类型要求
 
 T (容器元素类型) 必须满足 EmplaceConstructible 的要求。

返回值

(无) (C++17 前)
到被插入元素的引用。 (C++17 起)

复杂度

常数。

异常

若抛异常,则此函数无效果(强异常保证)。

pop_front
移除首元素 (公开成员函数)
void pop_front();
  (C++11 起)
     

移除容器首元素。若容器中无元素,则行为未定义。

指向被擦除元素的迭代器和引用被非法化。

参数

(无)

返回值

(无)

复杂度

常数。

异常

不抛出。

resize
改变容器中可存储元素的个数 (公开成员函数)
void resize( size_type count );
(1)  
void resize( size_type count, const value_type& value );
(2)  
     

重设容器大小以容纳 count 个元素。

若当前大小大于 count ,则减小容器为其首 count 个元素。

若当前大小小于 count ,

1) 则后附额外的 默认插入的元素
2) 则后附额外的  value 的副本

参数

count - 容器的大小
value - 用以初始化新元素的值
类型要求
 
  为使用重载 (1) , T 必须满足 DefaultInsertable 的要求。
 
  为使用重载 (2) , T 必须满足 CopyInsertable 的要求。

返回值

(无)

复杂度

与当前大小和 count 间的差成线性。可能有源于遍历链表以抵达首个要擦除元素/插入位置结尾的额外复杂度。

swap
交换内容 (公开成员函数)
void swap( forward_list& other );
  (C++11 起) 
(C++17 前)
void swap( forward_list& other noexcept(/* see below */);
  (C++17 起)
     

将内容与 other 的交换。不在单个元素上调用任何移动、复制或交换操作。

所有迭代器和引用保持合法。在操作后,保有此容器中尾后值的迭代器指代此容器或另一容器是未指定的。

 

若 std::allocator_traits<allocator_type>::propagate_on_container_swap::value 为 true ,则用非成员 swap 的非限定调用交换分配器。否则,不交换它们(且若 get_allocator(!= other.get_allocator() ,则行为未定义)。 (C++11 起)

参数

other - 要与之交换内容的容器

返回值

(无)

异常

(无)

(C++17 前)
noexcept 规定:  
noexcept(std::allocator_traits<Allocator>::is_always_equal::value)
(C++17 起)

复杂度

常数。

 example

 1 #include<iostream>
 2 #include<string>
 3 #include<forward_list>
 4 #include<ctime>
 5 #include<vector>
 6 using namespace std;
 7  
 8 int main()
 9 {
10     forward_list<string> str{"Hello","World"};
11  
12     cout << "str: " << str.front() <<  endl;
13     str.clear();
14     if (!str.empty())
15         cout << "str: " << str.front() << endl;
16  
17  
18     forward_list<int> mylist{1,2,3,4,5,6};
19  
20     forward_list<int>::iterator it = mylist.begin();
21     ++it;
22  
23     it = mylist.insert_after(it, 10);                  // 1 10 2 3 4 5
24     // "it" now points to the newly inserted 10
25  
26     mylist.insert_after(it, 2, 20);                     // 1 20 20 10 2 3 4 5
27     // "it" no longer valid!
28  
29     it = mylist.begin();
30  
31     vector<int> myvector(2, 30);
32     mylist.insert_after(it, myvector.begin(), myvector.end());
33     // 1 20 30 30 20 10 2 3 4 5
34  
35     cout << "mylist contains:";
36     for (it = mylist.begin(); it != mylist.end(); ++it)
37         cout << ' ' << *it;
38     cout << '\n';
39  
40     forward_list<int> mylist1 = { 10, 20, 30 };
41  
42     auto it1 = mylist1.emplace_after(mylist1.begin(), 100);
43     mylist1.emplace_after(it1, 200);
44  
45     cout << "mylist1 contains:";
46     for (auto& x : mylist1)
47         cout << ' ' << x;
48     cout << '\n';
49  
50  
51     forward_list<string> str1{"Hello","World"};
52  
53     cout << "str1: " << str1.front()   << endl;
54     if (!str1.empty())
55         cout << "str1: " << str1.front() << endl;
56  
57  
58  
59  
60     forward_list<int> arr{ 1, 2, 3, 4, 5, 6 };
61     for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
62         cout << *it << ' ';
63     cout << endl;
64  
65  
66  
67     //移除首元素 
68     arr.pop_front();
69     cout << "pop_front:" << endl;
70     for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
71         cout << *it << ' ';
72     cout << endl;
73  
74     //交换
75     forward_list<int>arr1(5, 9);
76     arr1.swap(arr);
77     
78     for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
79         cout << *it << ' ';
80     cout << endl;
81  
82     //首元素插入
83     arr.emplace_front(66);
84     arr.emplace_front(66);
85     arr.emplace_front(66);
86     cout << "emplace_front:" << endl;
87     for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
88         cout << *it << ' ';
89     cout << endl;
90  
91  
92  
93     system("pause");
94     return 0;
95 }

6、操作

操作
merge
合并二个已排序列表 (公开成员函数)
void merge( forward_list& other );
(1) (C++11 起)
void merge( forward_list&& other );
(1) (C++11 起)
template <class Compare
void merge( forward_list& other, Compare comp );
(2) (C++11 起)
template <class Compare
void merge( forward_list&& other, Compare comp );
(2) (C++11 起)
     

归并二个已排序链表为一个。链表应以升序排序。

不复制元素。操作后容器 other 变为空。若 this == &other 则函数不做任何事。若 get_allocator(!= other.get_allocator() ,则行为未定义。没有引用和迭代器变得非法,除了被移动元素的迭代器现在指代到 *this 中,而非到 other 中,第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp 。

此操作是稳定的:对于二个链表中的等价元素,来自 *this 的元素始终前驱来自 other 的元素,而且 *this 和 other 的等价元素顺序不更改。

参数

other - 要交换的另一容器
comp - 比较函数对象(即满足比较 (Compare) 概念的对象),若第一参数小于(即序于)第二参数则返回 ​true 。

比较函数的签名应等价于如下者:

 bool cmp(const Type1 &a, const Type2 &b);

签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 forward_list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。 ​

返回值

(无)

异常

若抛出异常,则此函数无效果(强异常保证),除非异常来自比较函数。

复杂度

至多 std::distance(begin(), end()std::distance(other.begin(), other.end()1 次比较。

splice_after
从另一 forward_list 移动元素 (公开成员函数)
void splice_after( const_iterator pos, forward_list& other );
(1) (C++11 起)
void splice_after( const_iterator pos, forward_list&& other );
(1) (C++11 起)
void splice_after( const_iterator pos, forward_list& other, 
                   const_iterator it );
(2) (C++11 起)
void splice_after( const_iterator pos, forward_list&& other,
                   const_iterator it );
(2) (C++11 起)
void splice_after( const_iterator pos, forward_list& other, 
                   const_iterator first, const_iterator last );
(3) (C++11 起)
void splice_after( const_iterator pos, forward_list&& other, 
                   const_iterator first, const_iterator last );
(3) (C++11 起)
     

从另一 forward_list 移动元素到 *this 。

不复制元素。 pos 为 *this 中的合法迭代器,或 before_begin() 迭代器。若 get_allocator(!= other.get_allocator() 则行为未定义。没有迭代器或引用被非法化,指向被移动的元素的迭代器现在指代到 *this 中,而非 other 中。

1) 从  other 移动所有元素到  *this 。元素被插入到  pos 所指向的元素后。操作后  other 变为空。若  this == &other 则行为未定义。
2) 从  other 移动后随  it 的迭代器所指向的元素到  *this 。元素被插入到  pos 所指向的元素后,若  pos==it 或若  pos==++it 则无效果。
3) 从  other 移动范围  (first, last) 中的元素到  *this 。元素被插入到  pos 所指向的元素后。不移动  first 所指向的元素。若  pos 是范围  (first,last) 中的元素则行为未定义。

参数

pos - 指向将插入内容到其后的元素的迭代器
other - 移动内容来源的另一容器
it - 指向从 other 移动到 *this 的元素的迭代器的前趋迭代器
first, last - 从 other 移动到 *this 的元素范围

返回值

(无)

复杂度

1) 与  other 的大小成线性
2) 常数
3) 与  std::distance(first, last) 成线性
remove
remove_if
移除满足特定标准的元素 (公开成员函数)
void removeconst T& value );
  (C++11 起)
templateclass UnaryPredicate >
void remove_if( UnaryPredicate p );
  (C++11 起)
     

移除所有满足特定标准的元素。第一版本移除所有等于 value 的元素,第二版本移除所有谓词 p 对它返回 true 的元素。

参数

value - 要移除的元素的值
p - 是否应移除该元素则返回 true 的一元谓词。

谓词函数签名应等价于如下者:

 bool pred(const Type &a);

签名不必拥有 const & ,但函数必须不修改传递给它的对象。
类型 Type 必须使得 forward_list<T,Allocator>::const_iterator 类型对象能在解引用后隐式转换到 Type 。 ​

返回值

(无)

复杂度

与容器大小成线性

reverse
将该链表的所有元素的顺序反转 (公开成员函数)
void reverse(noexcept;
  (C++11 起)
     

逆转容器中的元素顺序。不非法化任何引用或迭代器。

参数

(无)

返回值

(无)

参数

与容器大小成线性

unique
删除连续的重复元素 (公开成员函数)
void unique();
(1) (C++11 起)
templateclass BinaryPredicate >
void unique( BinaryPredicate p );
(2) (C++11 起)
     

从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。第一版本用 operator== 比较元素,第二版本用二元谓词 p比较元素

参数

p - 若元素应被当做相等则返回 ​true 的二元谓词。

谓词函数的签名应等价于如下者:

 bool pred(const Type1 &a, const Type2 &b);

签名不必拥有 const & ,但函数必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 forward_list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。

返回值

(无)

复杂度

与容器大小成线性

sort
对元素进行排序 (公开成员函数)
void sort();
(1) (C++11 起)
templateclass Compare 
void sort( Compare comp );
(2) (C++11 起)
     

以升序排序元素。保持相等元素的顺序。第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp 。

若抛出异常,则 *this 中元素顺序未指定。

参数

comp - 比较函数对象(即满足比较 (Compare) 概念的对象),若第一参数小于(即序于)第二参数则返回 ​true 。

比较函数的签名应等价于如下者:

 bool cmp(const Type1 &a, const Type2 &b);

签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 forward_list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。 ​

返回值

(无)

复杂度

大约 N log N 次比较,其中 N 是表中的元素数。

注意

std::sort 要求随机访问迭代器且不能用于 forward_list 。此函数与 std::sort 的区别在于,它不要求 forward_list 的元素类型可交换,保留所有迭代器的值,并进行稳定排序。

example

 1 #include<iostream>
 2 #include<forward_list>
 3  
 4 using namespace std;
 5  
 6 template<typename T>
 7 ostream&operator<<(ostream&s, const forward_list<T>&list)
 8 {
 9     for (auto &i : list)
10     {
11         s << " " << i;
12     }
13     return s;
14 }
15 int main()
16 {
17     forward_list<int>list1{ 1, 6, 3, 6, 2, 8 };
18     forward_list<int>list2{ 7, 4, 2, 8, 6, 4, 9 };
19  
20     //列表元素排序
21     list1.sort();
22     list2.sort();
23  
24     cout << "list1:" << list1 << endl;
25     cout << "list2:" << list2 << endl;
26     list1.merge(list2);
27     cout << "list1 merge:" << list1 << endl;
28  
29  
30     advance(list1.begin(), 0);
31     cout << "list1 advace:" << list1 << endl;
32     //从一个 list 转移元素给另一个。
33     //不复制或移动元素,仅重指向链表结点的内部指针。
34     list1.splice_after(list1.cbegin(), list2);//将list2所有元素放置到list1中
35     cout << "list1:" << list1 << endl;
36     cout << "list2:" << list2 << endl;
37  
38     将list1所有元素放置到list2中
39     list2.splice_after(list2.before_begin(), list1, list1.cbegin(), list1.cend());
40     cout << "list1:" << list1 << endl;
41     cout << "list2:" << list2 << endl;
42  
43     list2.remove(6);// 移除所有等于 6的元素
44     cout << "list2:" << list2 << endl;
45  
46     list2.remove_if([](int n){ return n > 6; }); // 移除全部大于 6 的元素
47     cout << "list2:" << list2 << endl;
48     
49     //列表反转
50     list2.reverse();
51     cout << "list2:" << list2 << endl;
52  
53     //从容器移除所有相继的重复元素。
54     list2.unique();
55     cout << "list2:" << list2 << endl;
56  
57     system("pause");
58     return 0;
59 }

7、非成员函数

operator==
operator!=
operator<
operator<=
operator>
operator>=
按照字典顺序比较 forward_list 中的值 (函数模板)
templateclass T, class Alloc >

bool operator==const forward_list<T,Alloc>& lhs,

                 const forward_list<T,Alloc>& rhs );
(1)  
templateclass T, class Alloc >

bool operator!=const forward_list<T,Alloc>& lhs,

                 const forward_list<T,Alloc>& rhs );
(2)  
templateclass T, class Alloc >

bool operator<const forward_list<T,Alloc>& lhs,

                const forward_list<T,Alloc>& rhs );
(3)  
templateclass T, class Alloc >

bool operator<=const forward_list<T,Alloc>& lhs,

                 const forward_list<T,Alloc>& rhs );
(4)  
templateclass T, class Alloc >

bool operator>const forward_list<T,Alloc>& lhs,

                const forward_list<T,Alloc>& rhs );
(5)  
templateclass T, class Alloc >

bool operator>=const forward_list<T,Alloc>& lhs,

                 const forward_list<T,Alloc>& rhs );
(6)  
     

比较二个容器的内容。

1-2) 检查  lhs 与  rhs 的内容是否相等,即是否  lhs.size(== rhs.size() 且每个  lhs 中的元素与  rhs 的同位置元素比较相等。
3-6) 按字典序比较  lhs 与  rhs 的内容。按照等价于  std::lexicographical_compare 的函数进行比较。

参数

lhs, rhs - 要比较内容的容器
 
  为使用重载 (1-2) , T 必须满足 EqualityComparable 的要求。
 
  为使用重载 (3-6) , T 必须满足 LessThanComparable 的要求。顺序关系必须建立全序。

返回值

1) 若容器内容相等则为  true ,否则为  false
2) 若容器内容不相等则为  true ,否则为  false
3) 若  lhs 的内容按字典序 小于  rhs 的内容则为  true ,否则为  false
4) 若  lhs 的内容按字典序 小于或 等于  rhs 的内容则为  true ,否则为  false
5) 若  lhs 的内容按字典序 大于  rhs 的内容则为  true ,否则为  false
6) 若  lhs 的内容按字典序 大于或 等于  rhs 的内容则为  true ,否则为  false

复杂度

与容器大小成线性

std::swap(std::forward_list)
 
(C++11)
特化 std::swap 算法 (函数模板)
templateclass T, class Alloc >

void swap( forward_list<T,Alloc>& lhs, 

           forward_list<T,Alloc>& rhs );
  (C++11 起) 
(C++17 前)
templateclass T, class Alloc >

void swap( forward_list<T,Alloc>& lhs, 

           forward_list<T,Alloc>& rhs noexcept(/* see below */);
  (C++17 起)
     

为 std::forward_list 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。

参数

lhs, rhs - 要交换内容的容器

返回值

(无)

复杂度

常数。

异常

noexcept 规定:  
noexcept(noexcept(lhs.swap(rhs)))
(C++17 起)


example

 1  //deque comparisons
 2 #include <iostream>
 3 #include <forward_list>
 4 using namespace std;
 5 int main()
 6 {
 7     forward_list<int> a = { 10, 20, 30 };
 8     forward_list<int> b = { 10, 20, 30 };
 9     forward_list<int> c = { 30, 20, 10 };
10  
11     if (a == b) 
12         cout << "a and b are equal\n";
13     if (b != c) 
14         cout << "b and c are not equal\n";
15     if (b<c) 
16         cout << "b is less than c\n";
17     if (c>b) 
18         cout << "c is greater than b\n";
19     if (a <= b) 
20         cout << "a is less than or equal to b\n";
21     if (a >= b) 
22         cout << "a is greater than or equal to b\n";
23  
24     system("pause");
25     return 0;
26 }
posted @ 2020-11-19 15:41  Mr-xxx  阅读(522)  评论(0编辑  收藏  举报