一 简介
1. C++11开始,STL增加了 forward_list 容器。它的实现是 singly linked list(单链表), 支持 foward iterator (前向迭代器)。
2. 单聊表进行元素的插入和删除是比较快速的,改动指针的指向即可,但前提是知道待处理节点的前驱节点。
3. 由于性能原因,forward_List 并没有提供 size 函数,也不能直接处理最末元素。size 可通过如下进行计算:
forward_list c;
auto size = std::distance(c.begin(), c.end());
4. forward_list 插入和移除元素,不会导致指向其他元素的pointer、reference 和 iterator 失效。
5. forward_list 由于自身特性,提供了一些特殊的迭代器和元素操作成员函数,下面分别展开。
二 迭代器
before_begin 和 cbefore_begin
返回指向第一个元素之前迭代器。
前面说过,例如插入需要知道前驱节点,那如果在开头插入,所以需要知道开头(begin)的前驱,也就是before_begin。
三 操作函数
其特殊的元素操作函数,是一批 xxx_after 函数。它们的处理范围也比较特殊。
1. 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 起)
template< class 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:
// 为不影响阅读逻辑,打印数据均进行注释,下同
std::forward_list<int> c1 {1,2,3,4,5,6,7};
// print("original c1:", c1);
c1.insert_after(c1.before_begin(), 10);
// print("1 insert_after c1:", c1);
c1.insert_after(c1.begin(), 3, 30);
// print("2 insert_after c1:", c1);
std::forward_list<int> temp_c {100,200,300};
c1.insert_after(c1.before_begin(), temp_c.begin(), temp_c.end());
// print("3 insert_after c1:", c1);
结果:
original c1:
1 2 3 4 5 6 7
1 insert_after c1:
10 1 2 3 4 5 6 7
2 insert_after c1:
10 30 30 30 1 2 3 4 5 6 7
3 insert_after c1:
100 200 300 10 30 30 30 1 2 3 4 5 6 7
注意:
(1)pos 必须是有效迭代器(指向有效元素) 或 before_begin。在 pos 的下一位置插入。
(2) insert_after(4) 处理的区间为 [begin, end)。
2. emplace_after
在容器中的指定位置后插入新元素。原位构造元素,即不进行复制或移动操作。
template< class... Args >
iterator emplace_after( const_iterator pos, Args&&... args ); (C++11 起)
例子2:
class A
{
public:
explicit A(int a = 0) {}
explicit A(int a, int b) {}
};
……
std::forward_list<A> temp_c;
A a1;
temp_c.insert_after(temp_c.before_begin(), a1);
temp_c.emplace_after(temp_c.before_begin(), 1);
temp_c.emplace_front(2,2);
// std::cout << "temp_c size:" << std::distance(temp_c.begin(), temp_c.end()) << std::endl;
结果:
temp_c size:3
3. erase_after
从容器移除指定元素。
iterator erase_after( const_iterator pos ); (1) (C++11 起)
iterator erase_after( const_iterator first, const_iterator last ); (2) (C++11 起)
例子3:
// 代码接例子1
// print("c1", c1);
auto it = std::next(c1.begin(), 9);
c1.erase_after(c1.begin(), it);
// print("1 erase_after c1:", c1);
c1.erase_after(it);
// print("2 erase_after c1:", c1);
结果:
c1:
100 200 300 10 30 30 30 1 2 3 4 5 6 7
1 erase_after c1:
100 3 4 5 6 7
2 erase_after c1:
100 3 5 6 7
注意:
(1)erase_after(1) 移除的是 pos 的下一位置元素。(it 指向元素3, 第一次 erase_after 后仍有效;第二次 erase_after 移除的是其后的元素4)
(2)erase_after(2) 处理的区间为 (begin, end) 开区间。
4. splice_after
从另一 forward_list 移动元素到 *this 。不复制元素。
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 起)
例子4:
// 代码接例子3
// print("c1:", c1);
std::forward_list<int> temp_c {1000,2000,3000};
// print("original temp_c:", temp_c);
c1.splice_after(c1.before_begin(), temp_c);
// print("splice_after temp_c:", temp_c);
// print("splice_after c1:", c1);
std::forward_list<int> temp1_c {7000,8000,9000};
// print("original temp1_c:", temp1_c);
c1.splice_after(c1.before_begin(), temp1_c, temp1_c.begin());
// print("splice_after temp1_c:", temp1_c);
// print("splice_after c1:", c1);
c1.splice_after(c1.before_begin(), temp1_c, temp1_c.begin(), temp1_c.end());
// print("splice_after temp1_c:", temp1_c);
// print("splice_after c1:", c1);
结果:
c1:
100 3 5 6 7
original temp_c:
1000 2000 3000
splice_after temp_c:
splice_after c1:
1000 2000 3000 100 3 5 6 7
// -----------------------------
original temp1_c:
7000 8000 9000
splice_after temp1_c:
7000 9000
splice_after c1:
8000 1000 2000 3000 100 3 5 6 7
// -----------------------------
splice_after temp1_c:
7000
splice_after c1:
9000 8000 1000 2000 3000 100 3 5 6 7
注意:
(1)pos 必须是有效迭代器(指向有效元素) 或 before_begin。
(2)splice_after 是 move操作。(第一次操作后,temp_c 空了。)
(3)splice_after(2) move 的是 it 指向元素的下一元素。(第二次操作,move 的是 8000 而不是 7000。)
(4)splice_after(3) 处理的区间为 (begin, end) 开区间。(第三次操作,move 的是 9000 而不是 7000、9000。)
四 参考