list
底层数据结构
list同样是一个模板类,它底层数据结构为双向循环链表。因此,它支持任意位置常数时间的插入/删除操作,不支持快速随机访问。
迭代器类型
list的迭代器具备前移、后移的能力,所以list提供的是Bidirectional iterator(双向迭代器)。由于采用的是双向迭代器,自然也很方便在指定元素之前插入新节点,所以list很正常地提供了insert()操作与push_back()/pop_back()操作。在C++11中,list新增了三个接口,以支持在指定位置构造对象后插入容器中:
接口(C++11新增) 描述 emplace 在指定位置之前插入新构造的元素 emplace_front 在链表头插入新构造的元素 emplace_back 在链表尾插入新构造的元素内存分配策略
list的空间配置策略,自然是像我们普通双向链表那样,有多少元素申请多少内存。它不像vector那样需要预留空间供新元素的分配,也不会因找不到连续的空间而引起整个容器的内存迁移。
迭代器失效问题
list 有一个重要性质:插入操作(insert)与接合操作(splice)都不会造成原有的list迭代器失效。这在vector是不成立的,因为vactor的插入可能引起空间的重新配置,导致原来的迭代器全部失效。list的迭代器失效,只会出现在删除的时候,指向删除元素的那个迭代器在删除后失效。
通常来说,forward_list在使用灵活度上比不上list,因为它只能单向迭代元素,且提供的接口没有list多。然而,在内存的使用上,它是比list占优势的。当对内存的要求占首要位置时,应该选择forward_list。
list使用优劣
优点:
(1) 不使用连续内存完成动态操作。
(2) 在内部方便的进行插入和删除操作
(3) 可在两端进行push、pop
缺点:
(1) 不能进行内部的随机访问,即不支持[ ]操作符和vector.at()
(2) 相对于verctor占用内存多
定义于头文件 <list> template<
class T, class Allocator = std::allocator<T>
> class list; (1) namespace pmr {template <class T> using list = std::list<T, std::pmr::polymorphic_allocator<T>>;
}1、
const T& value = T(),
const Allocator& alloc = Allocator());(C++11 前) list( size_type count,const T& value,
const Allocator& alloc = Allocator());(C++11 起) (3) explicit list( size_type count ); (C++11 起) (C++14 前) explicit list( size_type count, const Allocator& alloc = Allocator() ); (C++14 起) template< class InputIt >list( InputIt first, InputIt last,
const Allocator& alloc = Allocator() ); (4) list( const list& other ); (5) list( const list& other, const Allocator& alloc ); (5)(C++11 起) list( list&& other ); (6)(C++11 起) list( list&& other, const Allocator& alloc ); (7)(C++11 起) list( std::initializer_list<T> init, const Allocator& alloc = Allocator() ); (8)(C++11 起)从各种数据源构造新容器,可选地使用用户提供的分配器 alloc 。
1) 默认构造函数。构造空容器。 2) 构造拥有 count 个有值 value 的元素的容器。 3) 构造拥有个 count 默认插入的 T 实例的容器。不进行复制。 4) 构造拥有范围 [first, last) 内容的容器。 若 InputIt 是整数类型,则此构造函数拥有的效果同 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 内容的容器。到 Allocator::allocate 的调用可能抛出。
在容器移动构造(重载 (6) )后,指向 other 的引用及迭代器(除了尾迭代器)保持合法,但指代现于 *this 中的元素。
(析构函数) 析构 list (公开成员函数) operator= 赋值给容器 (公开成员函数) list& operator=( const list& other ); (1) (2) list& operator=( list&& other ); (C++11 起) (C++17 前) list& operator=( list&& other ) noexcept(/* see below */); (C++17 起) 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 所标识者替换内容。*this
容器移动赋值(重载 (2) )后,除非不兼容的分配器强制逐元素赋值,否则指向 other 的引用、指针和迭代器(除了尾迭代器)都保持合法,不过指代的元素现在在 *this 中。
assign 将值赋给容器 (公开成员函数) void assign( size_type count, const T& value ); (1) template< class InputIt > void assign( InputIt first, InputIt last ); (2) void assign( std::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 的元素替换内容。所有指向容器元素的迭代器、指针及引用均被非法化。
返回与容器关联的分配器。
(无)
关联的分配器。
常数。
#include<iostream> #include<string> #include<list> using namespace std; //队列重载<< template<typename T> ostream& operator<<(ostream& s, const list<T>& v) { s.put('['); char comma[3] = { '\0', ' ', '\0' }; for (const auto& e : v) { s << comma << e; comma[0] = ','; } return s << ']'; } int main() { list<int>lst; lst.push_back(1); lst.push_back(2); lst.push_back(3); cout << "lst:" << lst << endl; list<int>lst1(lst.begin(), lst.end()); cout << "lst1:" << lst1 << endl; //复制构造 list<int>lst2(lst); cout << "lst2:" << lst2 << endl; list<string>lst3(5, "AB"); cout << "lst3:" << lst3 << endl; list<int>num1{ 1, 2, 3, 4, 5, 6 }; list<int>num2; list<int>num3; cout << "num1:" << num1 << endl; // 复制赋值会从 nums1 复制数据到 nums2 num2 = num1; cout << "num2:" << num2 << endl; // 移动赋值会从 nums1 移动数据到 nums3 num3 = move(num2); cout << "num3:" << num3 << endl; list<char>ch; ch.assign(6, '*'); cout << "ch:" << ch << endl; //重新初始化对象 num1.assign(2, 6); cout << "num1:" << num1 << endl; // list<char>ch1; ch1.assign(ch.begin(), ch.end()); cout << "ch1:" << ch1 << endl; list<int> mylst; int * p; unsigned int i; //分配数组5个元素的空间用于deque分配器 p = mylst.get_allocator().allocate(5); // 空间中赋值 for (i = 0; i<5; i++) mylst.get_allocator().construct(&p[i], i); cout << "The allocated array contains:"; for (i = 0; i<5; i++) cout << ' ' << p[i]; cout << '\n'; // 销毁空间 for (i = 0; i<5; i++) mylst.get_allocator().destroy(&p[i]); lst.get_allocator().deallocate(p, 5); system("pause"); return 0; }
2、
返回到容器首元素的引用。
在空容器上对 front 的调用是未定义的。
(无)
到首元素的引用
常数
对于容器 c ,表达式 c.front() 等价于 *c.begin() 。
back 访问最后一个元素 (公开成员函数) reference back(); const_reference back() const;返回到容器中最后一个元素的引用。
在空容器上对 back 的调用是未定义的。
(无)
到最后元素的引用。
常数。
对于容器 c ,表达式 return c.back(); 等价于 { auto tmp = c.end(); --tmp; return *tmp; }
示例省略,注意元素访问无operater[ ]和at。
3、
返回指向容器首元素的迭代器。
若容器为空,则返回的迭代将等于 end() 。
(无)
指向首元素的迭代器
常数
end cend 返回指向容器尾端的迭代器 (公开成员函数) iterator end(); (C++11 前) iterator end() noexcept; (C++11 起) const_iterator end() const; (C++11 前) const_iterator end() const noexcept; (C++11 起) const_iterator cend() const noexcept; (C++11 起)返回指向后随容器最后元素的元素的迭代器。
此元素表现为占位符;试图访问它导致未定义行为。
(无)
指向后随最后元素的迭代器。
常数。
rbegin crbegin 返回一个指向容器最后一个元素的反向迭代器 (公开成员函数) reverse_iterator rbegin(); (C++11 前) reverse_iterator rbegin() noexcept; (C++11 起) const_reverse_iterator rbegin() const; (C++11 前) const_reverse_iterator rbegin() const noexcept; (C++11 起) const_reverse_iterator crbegin() const noexcept; (C++11 起)返回值指向逆向容器的首元素。它对应非逆向容器的最末元素。
(无)
指向首元素的逆向迭代器。
常数
rend crend 返回一个指向容器前端的反向迭代器 (公开成员函数) reverse_iterator rend(); (C++11 前) reverse_iterator rend() noexcept; (C++11 起) const_reverse_iterator rend() const; (C++11 前) const_reverse_iterator rend() const noexcept; (C++11 起) const_reverse_iterator crend() const noexcept; (C++11 起)返回逆向容器末元素的后一元素。它对应非逆向容器首元素的前一元素。此元素表现为占位符,试图访问它导致未定义行为。
(无)
指向末元素后一元素的逆向迭代器。
常数。
#include<iostream> #include<string> #include<list> using namespace std; int main() { list<string>str; str.assign(2, "abac"); str.push_back("aaa"); str.push_back("bbb"); str.push_back("ccc"); //迭代器 list<string>::iterator iter = str.begin(); for (; iter != str.end();) { cout << *iter++ << ' '; } cout << endl; //常迭代器 list<string>::const_iterator iter1 = str.begin(); for (; iter1 != str.end();) { cout << *iter1++ << ' '; } cout << endl; //常反迭代器 list<string>::const_reverse_iterator iter2 = str.rbegin(); for (; iter2 != str.rend();) { cout << *iter2++ << ' '; } cout << endl; system("pause"); return 0; }
4、
检查容器是否无元素,即是否 begin() == end() 。
(无)
若容器为空则为 true ,否则为 false
常数。
size 返回容纳的元素数 (公开成员函数) size_type size() const; (C++11 前) size_type size() const noexcept; (C++11 起)返回容器中的元素数,即 std::distance(begin(), end()) 。
(无)
容器中的元素数量。
常数。
max_size 返回可容纳的最大元素数 (公开成员函数) size_type max_size() const; (C++11 前) size_type max_size() const noexcept; (C++11 起)返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。
(无)
元素数量的最大值。
常数。
此值典型地反映容器大小上的理论极限。运行时,容器的大小可能被可用 RAM 总量限制到小于 max_size() 的值。
注意:无 shrink_to_fit ( )函数#include<iostream> #include<string> #include<list> #include<ctime> using namespace std; int main() { srand(time(0)); list<char> ch; for (int i = 0; i < 10; i++) ch.push_back((char)rand() % 10); cout << "ch size:" << ch.size() << endl; if (ch.empty() == 0) cout << "ch is null" << endl; ch.resize(20); //容器可保有的元素最大数量 cout << "ch max_size:" << ch.max_size() << endl; system("pause"); return 0; }
5、
从容器移除所有元素。
非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器保持合法。
(无)
(无)
与容器大小,即元素数成线性。
insert 插入元素 (公开成员函数) iterator insert( iterator pos, const T& value ); (C++11 前) iterator insert( const_iterator pos, const T& value ); (C++11 起) iterator insert( const_iterator pos, T&& value ); (2)(C++11 起) (3) void insert( iterator pos, size_type count, const T& value ); (C++11 前) iterator insert( const_iterator pos, size_type count, const T& value ); (C++11 起) (4) template< class InputIt > void insert( iterator pos, InputIt first, InputIt last);(C++11 前) template< class InputIt > iterator insert( const_iterator pos, InputIt first, InputIt last );(C++11 起) iterator insert( const_iterator pos, std::initializer_list<T> ilist ); (5)(C++11 起)插入元素到容器中的指定位置。
1-2) 在 pos 前插入 value 。 3) 在 pos 前插入 value 的 count 个副本。 4) 在 pos 前插入来自范围 [first, last) 的元素。 若 InputIt 为整数类型,则此重载与重载 (3) 拥有相同效果。 (C++11 前) 此重载仅若 InputIt 足以为输入迭代器 (InputIterator) 才参与重载决议,以避免与重载 (3) 有歧义。 (C++11 起) 若 first 和 last 是指向 *this 中的迭代器,则行为未定义。 5) 在 pos 前插入来自 initializer_list ilist 的元素。没有引用和迭代器被非法化。
若抛出异常,则无效果(强异常保证)。
emplace (C++11) 原位构造元素 (公开成员函数) template< class... Args > iterator emplace( const_iterator pos, Args&&... args ); (C++11 起)直接于 pos 前插入元素到容器中。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args... 作为 std::forward<Args>(args)... 转发给构造函数。
没有引用和迭代器被非法化。
指向被安置的元素的迭代器。
常数。
若抛异常(例如由构造函数),则保留容器不修改,如同未曾调用过此函数(强异常保证)。
erase 擦除元素 (公开成员函数 iterator erase( iterator pos ); (C++11 前) iterator erase( const_iterator pos ); (C++11 起) (2) iterator erase( iterator first, iterator last ); (C++11 前) iterator erase( const_iterator first, const_iterator last ); (C++11 起)从容器移除指定的元素。
1) 移除位于 pos 的元素。 2) 移除范围 [first; last) 中的元素。指向被擦除元素的迭代器和引用被非法化。其他引用和迭代器不受影响。
迭代器 pos 必须合法且可解引用。从而不能以 end() 迭代器(合法,但不可解引用)为 pos 的值。
若 first==last 则迭代器 first 不必可解引用:擦除空范围是无操作。
后随最后被移除元素的迭代器。若迭代器 pos 指代最后元素,则返回 end() 迭代器。
(无)
后附给定元素 value 到容器尾。
1) 初始化新元素为 value 的副本。 2) 移动 value 进新元素。没有引用和迭代器被非法化。
(无)
常数。
若抛出异常(可能因为 Allocator::allocate() 或元素复制/移动构造函数/赋值),则此函数无效果(强异常保证)。
emplace_back (C++11) 在容器末尾就地构造元素 (公开成员函数) template< class... Args > void emplace_back( Args&&... args ); (C++11 起) (C++17 前) template< class... Args > reference emplace_back( Args&&... args ); (C++17 起)添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args... 以 std::forward<Args>(args)... 转发到构造函数。
没有引用和迭代器被非法化。
常数。
若抛出异常,则此函数无效果(强异常保证)。
pop_back 移除末元素 (公开成员函数) void pop_back();移除容器的最末元素。
在空容器上调用 pop_back 是未定义的。
指向被擦除元素的迭代器和引用被非法化。
(无)
(无)
常数。
(无)
push_front 插入元素到容器起始 (公开成员函数) void push_front( const T& value ); void push_front( T&& value ); (C++11 起)前附给定元素 value 到容器起始。
没有引用和迭代器被非法化。
(无)
常数。
若抛出异常,则此函数无效果(强异常保证)。
emplace_front (C++11) 在容器头部就地构造元素 (公开成员函数) template< class... Args > void emplace_front( Args&&... args ); (C++11 起) (C++17 前) template< class... Args > reference emplace_front( Args&&... args ); (C++17 起)插入新元素到容器起始。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args... 作为 std::forward<Args>(args)... 转发给构造函数。
没有引用和迭代器被非法化。
常数。
若抛异常,则此函数无效果(强异常保证)。
pop_front 移除首元素 (公开成员函数) void pop_front();移除容器首元素。若容器中无元素,则行为未定义。
指向被擦除元素的迭代器和引用被非法化。
(无)
(无)
常数。
不抛出。
resize 改变容器中可存储元素的个数 (公开成员函数) void resize( size_type count, T value = T() ); (C++11 前) void resize( size_type count ); (1)(C++11 起) void resize( size_type count, const value_type& value ); (2)(C++11 起)重设容器大小以容纳 count 个元素。
若当前大小大于 count ,则减小容器为其首 count 个元素。
若当前大小小于 count ,则后附额外元素,并以 value 的副本初始化。
(C++11 前)若当前大小小于 count ,
1) 则后附额外的 默认插入的元素 2) 则后附额外的 value 的副本 (C++11 起)(无)
与当前大小和 count 间的差成线性。。
swap 交换内容 (公开成员函数) void swap( list& other ); (C++17 前) void swap( 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 起)
(无)
(无)
(C++17 前) noexcept 规定: noexcept(std::allocator_traits<Allocator>::is_always_equal::value) (C++17 起)常数。
#include<iostream> #include<string> #include<list> #include<ctime> #include<vector> using namespace std; int main() { list<string> str; str.push_back("Hello"); str.push_back("World"); cout << "str: " << str.front() << " size:" << str.size() << endl; str.clear(); if (!str.empty()) cout << "str: " << str.front() << endl; else cout<< "size:" << str.size() << endl; list<int> mylist; //插入 // set some initial values: for (int i = 1; i<6; i++) mylist.push_back(i); // 1 2 3 4 5 list<int>::iterator it = mylist.begin(); ++it; it = mylist.insert(it, 10); // 1 10 2 3 4 5 // "it" now points to the newly inserted 10 mylist.insert(it, 2, 20); // 1 20 20 10 2 3 4 5 // "it" no longer valid! it = mylist.begin(); vector<int> myvector(2, 30); mylist.insert(it, myvector.begin(), myvector.end()); // 1 20 30 30 20 10 2 3 4 5 cout << "mylist contains:"; for (it = mylist.begin(); it != mylist.end(); ++it) cout << ' ' << *it; cout << '\n'; list<int> mylist1 = { 10, 20, 30 }; auto it1 = mylist1.emplace(mylist1.begin(), 100); mylist1.emplace(it1, 200); mylist1.emplace(mylist1.end(), 300); cout << "mylist1 contains:"; for (auto& x : mylist1) cout << ' ' << x; cout << '\n'; mylist1.emplace_back(100); mylist1.emplace_back(200); cout << "emplace_back:" << endl; cout << "mylist1 contains:"; for (auto& x : mylist1) cout << ' ' << x; cout << '\n'; list<string> str1; str1.push_back("Hello"); str1.push_back("world"); cout << "str1: " << str1.front() << " size:" << str1.size() << endl; str1.erase(str1.begin()); if (!str1.empty()) cout << "str1: " << str1.front() << " size:" << str1.size() << endl; else cout << "size:" << str1.size() << endl; list<int> arr{ 1, 2, 3, 4, 5, 6 }; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; //移除末元素 arr.pop_back(); cout << "pop_back:" << endl; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; //移除首元素 arr.pop_front(); cout << "pop_front:" << endl; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; //首元素插入 arr.push_front(6); arr.push_front(6); arr.push_front(6); cout << "push_front:" << endl; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; //交换 list<int>arr1(5, 9); cout << "arr1 size:" << arr1.size() << endl; arr1.swap(arr); cout << "arr1 size:" << arr1.size() << endl; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; //首元素插入 arr.emplace_front(66); arr.emplace_front(66); arr.emplace_front(66); cout << "emplace_front:" << endl; for (list<int>::iterator it = arr.begin(); it != arr.end(); it++) cout << *it << ' '; cout << endl; system("pause"); return 0; }
6、
归并二个已排序链表为一个。链表应以升序排序。
不复制元素。操作后容器 other 变为空。若 this == &other 则函数不做任何事。若 get_allocator() != other.get_allocator() ,则行为未定义。没有引用和迭代器变得非法,除了被移动元素的迭代器现在指代到 *this 中,而非到 other 中,第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp 。
此操作是稳定的:对于二个链表中的等价元素,来自 *this 的元素始终前驱来自 other 的元素,而且 *this 和 other 的等价元素顺序不更改。
比较函数的签名应等价于如下者:
bool cmp(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。 类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
(无)
若抛出异常,则此函数无效果(强异常保证),除非异常来自比较函数。
至多 std::distance(begin(), end()) + std::distance(other.begin(), other.end()) - 1 次比较。
splice 从另一个list中移动元素 (公开成员函数) void splice( const_iterator pos, list& other ); (1) void splice( const_iterator pos, list&& other ); (1)(C++11 起) void splice( const_iterator pos, list& other, const_iterator it ); (2) void splice( const_iterator pos, list&& other, const_iterator it ); (2)(C++11 起) void splice( const_iterator pos, list& other, const_iterator first, const_iterator last); (3) void splice( const_iterator pos, list&& other, const_iterator first, const_iterator last ); (3)(C++11 起)从一个 list 转移元素给另一个。
不复制或移动元素,仅重指向链表结点的内部指针。若 get_allocator() != other.get_allocator() 则行为未定义。没有迭代器或引用被非法化,指向被移动元素的迭代器保持合法,但现在指代到 *this 中,而非到 other 中。
1) 从 other 转移所有元素到 *this 中。元素被插入到 pos 所指向的元素之前。操作后容器 other 变为空。若 this == &other 则行为未定义。 2) 从 other 转移 it 所指向的元素到 *this 。元素被插入到 pos 所指向的元素之前。 3) 从 other 转移范围 [first, last) 中的元素到 *this 。元素被插入到 pos 所指向的元素之前。若 pos 是范围 [first,last) 中的迭代器则行为未定义。(无)
1-2) 常数。
3) 若 this == &other 则为常数,否则与 std::distance(first, last) 成线性。
remove remove_if 移除满足特定标准的元素 (公开成员函数) void remove( const T& value ); template< class UnaryPredicate > void remove_if( UnaryPredicate p );移除所有满足特定标准的元素。第一版本移除所有等于 value 的元素,第二版本移除所有谓词 p 对它返回 true 的元素。
谓词函数签名应等价于如下者:
bool pred(const Type &a);
签名不必拥有 const & ,但函数必须不修改传递给它的对象。 类型 Type 必须使得 list<T,Allocator>::const_iterator 类型对象能在解引用后隐式转换到 Type 。
(无)
与容器大小成线性
reverse 将该链表的所有元素的顺序反转 (公开成员函数) void reverse(); (C++11 前) void reverse() noexcept; (C++11 起)逆转容器中的元素顺序。不非法化任何引用或迭代器。
(无)
(无)
与容器大小成线性
unique 删除连续的重复元素 (公开成员函数) void unique(); (1) template< class BinaryPredicate > void unique( BinaryPredicate p ); (2)从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。第一版本用 operator== 比较元素,第二版本用二元谓词 p比较元素
谓词函数的签名应等价于如下者:
bool pred(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数必须不修改传递给它的对象。 类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
(无)
与容器大小成线性
sort 对元素进行排序 (公开成员函数) void sort(); (1) template< class Compare > void sort( Compare comp ); (2)以升序排序元素。保持相等元素的顺序。第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp 。
若抛出异常,则 *this 中元素顺序未指定。
比较函数的签名应等价于如下者:
bool cmp(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。 类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
(无)
大约 N log N 次比较,其中 N 是表中的元素数。
std::sort 要求随机访问迭代器且不能用于 list 。此函数与 std::sort 的区别在于,它不要求 list 的元素类型可交换,保留所有迭代器的值,并进行稳定排序。
#include<iostream> #include<list> using namespace std; template<typename T> ostream&operator<<(ostream&s, const list<T>&list) { for (auto &i : list) { s << " " << i; } return s; } int main() { list<int>list1{ 1, 6, 3, 6, 2, 8 }; list<int>list2{ 7, 4, 2, 8, 6, 4, 9 }; //列表元素排序 list1.sort(); list2.sort(); cout << "list1:" << list1 << endl; cout << "list2:" << list2 << endl; list1.merge(list2); cout << "list1 merge:" << list1 << endl; advance(list1.begin(), 0); cout << "list1 advace:" << list1 << endl; //从一个 list 转移元素给另一个。 //不复制或移动元素,仅重指向链表结点的内部指针。 list1.splice(list1.begin(), list2);//将list2所有元素放置到list1中 cout << "list1:" << list1 << endl; cout << "list2:" << list2 <<" size:"<<list2.size()<< endl; 将list1所有元素放置到list2中 list2.splice(list2.begin(), list1, list1.begin(), list1.end()); cout << "list1:" << list1 << endl; cout << "list2:" << list2 << endl; list2.remove(6);// 移除所有等于 6的元素 cout << "list2:" << list2 << endl; list2.remove_if([](int n){ return n > 6; }); // 移除全部大于 6 的元素 cout << "list2:" << list2 << endl; //列表反转 list2.reverse(); cout << "list2:" << list2 << endl; //从容器移除所有相继的重复元素。 list2.unique(); cout << "list2:" << list2 << endl; system("pause"); return 0; }
7、
bool operator==( const list<T,Alloc>& lhs,
const list<T,Alloc>& rhs ); (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)比较二个容器的内容。
1-2) 检查 lhs 与 rhs 的内容是否相等,即是否 lhs.size() == rhs.size() 且每个 lhs 中的元素与 rhs 的同位置元素比较相等。 3-6) 按字典序比较 lhs 与 rhs 的内容。按照等价于 std::lexicographical_compare 的函数进行比较。与容器大小成线性
std::swap(std::list) 特化 std::swap 算法 (函数模板) template< class T, class Alloc >
void swap( list<T,Alloc>& lhs,
list<T,Alloc>& rhs ); (C++17 前) template< class T, class Alloc >void swap( list<T,Alloc>& lhs,
list<T,Alloc>& rhs ) noexcept(/* see below */); (C++17 起)为 std::list 特化 std::swap 算法。交换 lhs 与 rhs 的内容。调用 lhs.swap(rhs) 。
(无)
常数。
#include <iostream> #include <list> using namespace std; int main() { list<int> a = { 10, 20, 30 }; list<int> b = { 10, 20, 30 }; list<int> c = { 30, 20, 10 }; if (a == b) cout << "a and b are equal\n"; if (b != c) cout << "b and c are not equal\n"; if (b<c) cout << "b is less than c\n"; if (c>b) cout << "c is greater than b\n"; if (a <= b) cout << "a is less than or equal to b\n"; if (a >= b) cout << "a is greater than or equal to b\n"; system("pause"); return 0; } swap:
//swap (deque overload) #include <iostream> #include <list> using namespace std; int main() { unsigned int i; list<int> foo(3, 100); // three ints with a value of 100 list<int> bar(5, 200); // five ints with a value of 200 swap(foo, bar); cout << "foo contains:"; for (list<int>::iterator it = foo.begin(); it != foo.end(); ++it) cout << ' ' << *it; cout << '\n'; cout << "bar contains:"; for (list<int>::iterator it = bar.begin(); it != bar.end(); ++it) cout << ' ' << *it; cout << '\n'; system("pause"); return 0; }
自定义类测试:
#include<iostream> #include<list> using namespace std; class Myclass { public : Myclass(int a, int b_) :b(b_) { this->a = a; } void fun() { cout << "My fun" << endl; } int b; private: int a; }; int main() { list<Myclass*>lst; Myclass *p = new Myclass(5,6); lst.push_back(p); lst.front()->fun(); cout << lst.front()->b << endl; system("pause"); return 0; }待续。。。。。。。