目录
1.1 constructor、destructor、operator=
2. Non-member function overloads
list
template < class T, class Alloc = allocator<T> > class list;
list是序列式容器,允许在序列内的任何地方进行恒定时间的插入和删除操作,以及双向的迭代。
list容器被实现为双向链表;双向链表可以将它们包含的每个元素存储在不同的、不相关的存储位置。顺序是通过每个元素与前面的元素和后面的元素的链接在内部保持的。
它们与forward_list非常相似:主要的区别是forward_list对象是单向链表,因此它们只能向前迭代,以换取更小和更高的效率。
与其他基本的标准序列式容器(array、vector和deque)相比,list在插入、提取和移动容器内任何已经获得迭代器的位置上的元素时通常表现得更好,因此在密集使用这些元素的算法中也是如此,比如排序算法。
与其他序列式容器相比,list和forward_list的主要缺点是它们缺乏对元素位置的直接访问;例如,要访问列表中的第六个元素,必须从一个已知的位置(如开头或结尾)迭代到该位置,这需要在这些距离中花费线性时间。它们也会消耗一些额外的内存来保持与每个元素相关的链接信息(这对于小尺寸元素的大列表来说可能是一个重要因素)。
list定义在头文件list和命名空间std中。
1. Member functions
1.1 constructor、destructor、operator=
1.1.1 constructor
// default (1)
explicit list(const allocator_type& alloc = allocator_type());
// fill(2)
explicit list(size_type n);
list(size_type n, const value_type& val, const allocator_type& alloc = allocator_type());
// range(3)
template <class InputIterator> list(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
// copy(4)
list(const list& x);
list(const list& x, const allocator_type& alloc);
// move(5)
list(list&& x);
list(list&& x, const allocator_type& alloc);
// initializer list(6)
list(initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
#include <list>
#include <string>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt1; // default
printLt(lt1); // 空
list<int> lt2(5); // fill
printLt(lt2); // 0 0 0 0 0
list<int> lt3(10, 1); // fill
printLt(lt3); // 1 1 1 1 1 1 1 1 1 1
string s("hello world");
list<char> lt4(s.begin() + 3, --s.end()); // range
printLt(lt4); // l o w o r l
list<char> lt5(lt4); // copy
// 等价于list<char> lt5 = lt4;
printLt(lt5); // l o w o r l
list<char> lt6(std::move(lt5)); // move
cout << "lt5: "; printLt(lt5); // lt5:
cout << "lt6: "; printLt(lt6); // lt6: l o w o r l
list<string> lt7{ "happy","new","year" }; // initializer list
// 等价于list<string> lt7 = { "happy","new","year" };
printLt(lt7); // happy new year
return 0;
}
1.1.2 destructor
~list();
1.1.3 operator=
// copy (1)
list& operator=(const list& x);
// move (2)
list& operator=(list&& x);
// initializer list (3)
list& operator=(initializer_list<value_type> il);
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt(5, 2);
printLt(lt); // 2 2 2 2 2
list<int> lt1;
lt1 = lt; // copy
printLt(lt1); // 2 2 2 2 2
list<int> lt2;
lt2 = std::move(lt1); // move
cout << "lt1: "; printLt(lt1); // lt1:
cout << "lt2: "; printLt(lt2); // lt2: 2 2 2 2 2
list<int> lt3;
lt3 = { 1,2,3,4,5,6 }; // initializer list
printLt(lt3); // 1 2 3 4 5 6
return 0;
}
1.2 Iterators
// begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
// end
iterator end() noexcept;
const_iterator end() const noexcept;
// rbegin
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
// rend
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
// cbegin
const_iterator cbegin() const noexcept;
// cend
const_iterator cend() const noexcept;
// crbegin
const_reverse_iterator crbegin() const noexcept;
// crend
const_reverse_iterator crend() const noexcept;
函数 | 功能 |
---|---|
& | begin返回一个迭代器,指向list中第一个元素 end返回一个迭代器,指向list中最后一个元素的下一个位置 |
& | rbegin返回一个反向迭代器,指向list中最后一个元素 rend返回一个反向迭代器,指向list中第一个元素的上一个位置 |
& | cbegin返回一个const迭代器,指向list中第一个元素 cend返回一个const迭代器,指向list中最后一个元素的下一个位置 |
& | crbegin返回一个const反向迭代器,指向list中最后一个元素 crend返回一个const反向迭代器,指向list中第一个元素的上一个位置 |
begin&end和rbegin&rend返回的迭代器指向:
const_iterator是一个指向const内容的迭代器。迭代器本身可以修改,但是它不能被用来修改它所指向的内容。
begin&end/rbegin&rend和cbegin&cend/crbegin&crend的不同:
- begin&end/rbegin&rend的返回类型由对象是否是常量来决定。如果不是常量,返回iterator;如果是常量,返回const_iterator。
- cbegin&cend/crbegin&crend的返回类型是const_iterator,不管对象本身是否是常量。
list迭代器的特点:不支持算数运算(+、-、+=、-=、-、>、>=、<、<=)。
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 4,5,6,7 };
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// 4 5 6 7
auto rit = lt.rbegin();
// list<int>::reverse_iterator rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// 7 6 5 4
return 0;
}
1.3 Capacity
1.3.1 empty
bool empty() const noexcept;
// 检测list是否为空,是返回true,否则返回false
1.3.2 size
size_type size() const noexcept;
// 返回list中元素的个数
1.3.3 max_size
size_type max_size() const noexcept;
// 返回list能够容纳的最大元素个数
Capacity系列函数使用示例:
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lt{ 4,5,6,7 };
if (lt.empty())
cout << "list为空" << endl;
else
cout << "list不为空" << endl;
// list不为空
cout << lt.size() << endl; // 4
cout << lt.max_size() << endl; // 357913941
return 0;
}
1.4 Element access
1.4.1 front
reference front();
const_reference front() const;
// 返回list中第一个元素的引用
1.4.2 back
reference back();
const_reference back() const;
// 返回list中最后一个元素的引用
Element access系列函数使用示例:
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lt{ 4,5,6,7 };
cout << lt.front() << endl; // 4
cout << lt.back() << endl; // 7
return 0;
}
1.5 Modifiers
1.5.1 assign
// range(1)
template <class InputIterator> void assign(InputIterator first, InputIterator last);
// fill(2)
void assign(size_type n, const value_type& val);
// initializer list(3)
void assign(initializer_list<value_type> il);
// 给list赋值,替换其当前内容
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt1{ 1,2,3,4 };
list<int> lt2{ 5,6,7,8,9 };
lt1.assign(++lt2.begin(), --lt2.end()); // range
printLt(lt1); // 6 7 8
lt1.assign(10, 1); // fill
printLt(lt1); // 1 1 1 1 1 1 1 1 1 1
lt1.assign({ 77,88 }); // initializer list
printLt(lt1); // 77 88
return 0;
}
1.5.2 emplace_front
template <class... Args> void emplace_front(Args&&... args);
// 对应push_front,区别是:
// 当调用push_front时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace_front时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素
1.5.3 push_front
void push_front(const value_type& val);
void push_front(value_type&& val);
// 头插
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 2,3,4 };
int val = 1;
lt.push_front(val);
printLt(lt); // 1 2 3 4
lt.push_front(0);
printLt(lt); // 0 1 2 3 4
return 0;
}
1.5.4 pop_front
void pop_front();
// 头删
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 2,3,4 };
lt.pop_front();
printLt(lt); // 3 4
lt.pop_front();
printLt(lt); // 4
return 0;
}
1.5.5 emplace_back
template <class... Args> void emplace_back(Args&&... args);
// 对应push_back,区别是:
// 当调用push_back时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace_back时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素
1.5.6 push_back
void push_back(const value_type& val);
void push_back(value_type&& val);
// 尾插
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 1,2,3 };
int val = 4;
lt.push_back(val);
printLt(lt); // 1 2 3 4
lt.push_back(5);
printLt(lt); // 1 2 3 4 5
return 0;
}
1.5.7 pop_back
void pop_back();
// 尾删
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 1,2,3 };
lt.pop_back();
printLt(lt); // 1 2
lt.pop_back();
printLt(lt); // 1
return 0;
}
1.5.8 emplace
template <class... Args> iterator emplace(const_iterator position, Args&&... args);
// 对应insert,区别是:
// 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素
1.5.9 insert
// single element(1)
iterator insert(const_iterator position, const value_type& val);
// fill(2)
iterator insert(const_iterator position, size_type n, const value_type& val);
// range(3)
template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last);
// move(4)
iterator insert(const_iterator position, value_type&& val);
// initializer list(5)
iterator insert(const_iterator position, initializer_list<value_type> il);
// 在position位置插入
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 1,2,3 };
int val = 4;
int arr[] = { 11,22 };
lt.insert(lt.end(), val); // single element
printLt(lt); // 1 2 3 4
lt.insert(lt.end(), 2, 5); // fill
printLt(lt); // 1 2 3 4 5 5
lt.insert(lt.begin(), arr, arr + 2); // range
printLt(lt); // 11 22 1 2 3 4 5 5
lt.insert(lt.begin(), 0); // move
printLt(lt); // 0 11 22 1 2 3 4 5 5
lt.insert(--lt.end(), { 99,88 }); // initializer list
printLt(lt); // 0 11 22 1 2 3 4 5 99 88 5
return 0;
}
1.5.10 erase
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
// 删除
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 1,2,3,4 };
lt.erase(++lt.begin());
printLt(lt); // 1 3 4
lt.erase(lt.begin(), --lt.end());
printLt(lt); // 4
return 0;
}
1.5.11 swap
void swap(list& x);
// 交换
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt1{ 1,2,3,4 };
list<int> lt2{ 9,8,7 };
lt1.swap(lt2);
printLt(lt1); // 9 8 7
printLt(lt2); // 1 2 3 4
return 0;
}
1.5.12 resize
void resize(size_type n);
void resize(size_type n, const value_type& val);
// 调整list的大小为n
// 如果n<当前的大小,多余的元素会被截掉
// 如果n>当前的大小,则:
// 1)如果没有指定填充元素,则使用默认构造函数
// 2)如果指定了填充元素val,则多出的空间用val填充
#include <list>
#include <iostream>
using namespace std;
template<typename T>
void printLt(list<T>& lt)
{
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
}
int main()
{
list<int> lt{ 1,2,3 };
lt.resize(6, 4);
printLt(lt); // 1 2 3 4 4 4
lt.resize(2);
printLt(lt); // 1 2
return 0;
}
1.5.13 clear
void clear() noexcept;
// 清空
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lt{ 1,2,3 };
lt.clear();
if (lt.empty())
cout << "lt被清空" << endl;
else
cout << "lt没被清空" << endl;
// lt被清空
return 0;
}
1.6 Operations
1.6.1 splice
// entire list (1)
void splice(const_iterator position, list& x);
void splice(const_iterator position, list&& x);
// single element (2)
void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);
// element range (3) 注意区间是[first, last),与forward_list不同
void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);
// 从另一个list转移元素
// 将元素从x转移到容器中,将它们插入到position位置,注意是转移,不是拷贝
1.6.2 remove
void remove(const value_type& val);
// 移除具有特定值的元素
1.6.3 remove_if
template <class Predicate> void remove_if(Predicate pred);
// 移除满足条件的元素
1.6.4 unique
// (1)
void unique();
// (2)
template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);
// 去重
1.6.5 merge
// (1)
void merge(list& x);
void merge(list&& x);
// (2)
template <class Compare> void merge(list& x, Compare comp);
template <class Compare> void merge(list&& x, Compare comp);
// 合并有序链表
// 将参数x合并到调用merge的链表中
1.6.6 sort
// (1)
void sort();
// (2)
template <class Compare> void sort(Compare comp);
// 排序链表
1.6.7 reverse
void reverse() noexcept;
// 反转链表
1.7 Observers
1.7.1 get_allocator
allocator_type get_allocator() const noexcept;
// 返回空间配置器
2. Non-member function overloads
2.1 relational operators
// (1)
template <class T, class Alloc> bool operator==(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (2)
template <class T, class Alloc> bool operator!=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (3)
template <class T, class Alloc> bool operator<(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (4)
template <class T, class Alloc> bool operator<=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (5)
template <class T, class Alloc> bool operator>(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (6)
template <class T, class Alloc> bool operator>=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
2.2 swap
template <class T, class Alloc> void swap(list<T, Alloc>& x, list<T, Alloc>& y);
3. list对象的遍历方法
3.1 迭代器
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lt{ 1,2,3,4 };
list<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
// 1 2 3 4
auto rit = lt.rbegin();
// list<int>::reverse_iterator rit = lt.rbegin();
while (rit != lt.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
// 4 3 2 1
return 0;
}
3.2 范围for
#include <list>
#include <iostream>
using namespace std;
int main()
{
list<int> lt{ 1,2,3,4 };
for (auto& e : lt)
{
cout << e << " ";
}
cout << endl;
// 1 2 3 4
return 0;
}