STL(标准模板库) |
您所在的位置:网站首页 › stl和标准库 › STL(标准模板库) |
概念:
STL:标准模板库,是C++标准库的重要组成部分,STL,英文全称 standard template library,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,STL 是一些容器、算法和其他一些组件的集合,所有容器和算法都是总结了几十年来算法和数据结构的研究成果,注意,这里提到的容器,本质上就是封装有数据结构的模板类,例如 list、vector、set、map 等, 由概念便可以知道,STL中的所有数据结构都是以模板的方式创建的 容器(数据结构),算法(算法),迭代器(算法访问容器元素的工具), C++ STL 一共提供了六大组件,包括 容器,算法,迭代器,仿函数,配接器和配置器 ,彼此可以组合套用。 容器通过配置器取得数据存储空间; 算法通过迭代器存取容器内容; 仿函数可以协助算法完成不同的策略变化; 配接器可以应用于容器、仿函数和迭代器。 容器:包括各种数据结构,如vector,queue, deque,,set, map,用来存放数据,分为序列式容器和关联式容器,实现的角度来讲是一种类模板。容器可分为:序列式容器,关联式容器 序列式:容器中的元素有顺序关系 关联式:容器中的元素不要求有顺序关系 2、算法:各种常用的算法,问题的解法,如sort (插入,快排,堆排序), search (二分查找),从实现的角度来讲是一种方法模板。 3、迭代器:从实现的角度来看,迭代器是一种将 operator,operator->,operator++,operator-等指针相关操作赋予重载的类模板,所有的 STL 容器都有自己的迭代器。是容器和算法的粘合剂,算法要通过迭代器才可以访问容器中的元素,迭代器会通过自己的方法找到容器中的元素, 4、仿函数:从实现的角度看,仿函数是一种重载了 operator() 的类或者类模板。可以帮助算法实现不同的策略。 5、配接器:一种用来修饰容器或者仿函数或迭代器接口(参数)的东西。 6、配置器:负责空间配置与管理,从实现的角度讲,配置器是一个实现了动态空间配置、空间管理,空间释放的类模板。 vector(向量) 怎么使用: 包含头文件vector和命名空间stdvector 容器以类模板 vector( T 表示存储元素的类型)的形式定义在 头文件中,并位于 std 命名空间中。 五种创建容器方法:(1)先创建空容器,再添加容器容量和元素 (2)创建的同时初始化容器元素 vector v5{a,b,c...} vector v5={a,b,c...} 创建的同时指定容器容量,不给出容器元素vector v4(n)说明:包含n个重复执行了值初始化的对象(即值为0) 创建的同时指定容器容量和重复元素vector v3(n,val)说明:包含n个重复的val元素 (5)通过存储元素类型相同的其它 vector 容器,也可以创建 的 vector 容器,例如: vector v1 vector v2(v1) vector v2 = v1 如果不想复制其它容器中所有的元素,可以用一对指针或者迭代器来指定初始值的范围,例如: 纯文本复制 int array[]={ 1,2,3}; std::vectorvalues(array, array+2);//values 将保存{1,2} std::vectorvalue1{ 1,2,3,4,5}; std::vectorvalue2(std::begin(value1),std::begin(value1)+3);//value2保存{1,2,3}vector模板的成员函数: 函数成员 函数功能 begin() 返回指向容器中第一个元素的迭代器。 end() 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 rbegin() 返回指向最后一个元素的迭代器。 rend() 返回指向第一个元素所在位置前一个位置的迭代器。 cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 size() 返回实际元素个数。 max_size() 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 resize() 改变实际元素的个数。resize(10):指定容量,不指定多出来的元素,系统默认用0代替(注意:此时被0代替的位置也有元素0);resize(10,23):指定容量,多出来的用23填补;如果指定的容量比原来小,多出来的则被删除,被删除的迭代器将失效 capacity() 返回当前容量.(不是容量元素个数),capacity 一般大于size的原因是为了避免 每次增加数据时都要重新分配内存,所以一般会 生成一个较大的空间,以便随后的数据插入,capacity返回的是以元素个数为单位的容量 empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 reserve() 为容器预留容量空间(注意预留的是容量空间,不要拿size()的返回值和reserve()的返回值作比较)。容器每一次存储新的内存,都会从新开辟新的空间如果提前知道容器元素个数和容器容量,可以提前为容器预留容量空间,reserve只适用于vector和string shrink _to_fit() 将内存减少到等于当前元素实际所使用的大小。 operator[ ] 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。 at() 使用经过边界检查的索引访问指定位置的元素。 front() 返回第一个元素的引用。 back() 返回最后一个元素的引用。 data() 返回指向容器中第一个元素的指针。 assign() 用新元素替换原有内容。 push_back() 一次在序列的尾部添加一个元素。 pop_back() 移出序列尾部的元素。 insert() 在指定的位置插入一个或多个元素。insert(++v1.begin(),50) erase() 移出一个元素或一段元素。erase(v1.begin(),v1.end()) clear() 移出所有的元素,容器大小变为 0。 swap() 交换两个容器的所有元素。 emplace() 在指定的位置直接生成一个元素。 emplace_back() 在序列尾部生成一个元素。 resize()增加容器元素个数才可以增加容器元素,reserve()增加容器容量,不可以增加容器元素 仅通过 reserve() 成员函数增加 value 容器的容量,其大小并没有改变;但通过 resize() 成员函数改变 value 容器的大小,它的容量可能会发生改变。另外需要注意的是,通过 resize() 成员函数减少容器的大小(多余的元素会直接被删除),不会影响容器的容量。 圆括号 () 和大括号 {} 是有区别的,前者(vectorv(20) )表示元素的个数,而后者(vectorv{20} ) 则表示 vector 容器中只有一个元素 20。 我们可能需要将容器的容量和大小保存在变量中,要知道 vector 对象的容量和大小类型都是 vector::size_type 类型。因此,当定义一个变量去保存这些值时,可以如下所示: vector::size_type cap = value.capacity(); vector::size_type size = value.size();size_type 类型是定义在由 vector 类模板生成的 vecotr 类中的,它表示的真实类型和操作系统有关,在 32 位架构下普遍表示的是 unsigned int 类型,而在 64 位架构下普通表示 unsigned long 类型。 迭代器的使用: 什么是迭代器: 迭代器就是地址 迭代器和 C++ 的指针非常类似,它可以是需要的任意类型,通过迭代器可以指向容器中的某个元素,如果需要,还可以对该元素进行读/写操作。 注意迭代器不是引用,可以用迭代器作实参传递去改变容器内容,但是形参不要定义为引用,直接定义为: template void container_change(I i){}; vector 支持迭代器的成员函数 成员函数 功能 begin() 返回指向容器中第一个元素的正向迭代器;如果是 const 类型容器,在该函数返回的是常量正向迭代器。 end() 返回指向容器最后一个元素之后一个位置的正向迭代器;如果是 const 类型容器,在该函数返回的是常量正向迭代器。此函数通常和 begin() 搭配使用。 rbegin() 返回指向最后一个元素的反向迭代器;如果是 const 类型容器,在该函数返回的是常量反向迭代器。 rend() 返回指向第一个元素之前一个位置的反向迭代器。如果是 const 类型容器,在该函数返回的是常量反向迭代器。此函数通常和 rbegin() 搭配使用。 cbegin() 和 begin() 功能类似,只不过其返回的迭代器类型为常量正向迭代器,不能用于修改元素。 cend() 和 end() 功能相同,只不过其返回的迭代器类型为常量正向迭代器,不能用于修改元素。 crbegin() 和 rbegin() 功能相同,只不过其返回的迭代器类型为常量反向迭代器,不能用于修改元素。 crend() 和 rend() 功能相同,只不过其返回的迭代器类型为常量反向迭代器,不能用于修改元素。 vector::iterator//vector模板类中的迭代器 vector模板和普通数组很相似,也叫单端数组。 vector容器和普通数组的区别: 普通数组的容量是固定的,vector容器的容量是可以变的,即动态的。 vector容量的动态扩展不是在原有空间的基础上增加新空间,而是找到更大的空间,把原数据拷贝到找到的空间,再释放原空间 vectorv2(v1.begin(),v1.end()); 将v1中所有的数据复制到v2中 同样功能可以用: vectorv2; v2.assign(v1.begin(),v1.end()); 怎么访问vector容器中的元素: v.at(n)返回容器位置为n的元素的引用(注意第一个位置为0) vector容器也是数组,可以用v[n]访问所谓泛型编程就是模板编程,泛型就是广泛可以使用的类型,即模板 五类主要的序列容器: vector,array,list,deque,forward_list array容器不是array数组,它如同其他容器拥有自己的成员函数 和其它容器不同,array 容器的大小是固定的,无法动态的扩展或收缩,这也就意味着,在使用该容器的过程无法借由增加或移除元素而改变其大小,它只允许访问或者替换存储的元素。 每一个容器的使用都要包含自己的头文件,头文件在std命名空间中 array容器的头文件: array容器的初始化: 1,array values; 由此,就创建好了一个名为 values 的 array 容器,其包含 10 个浮点型元素。但是,由于未显式指定这 10 个元素的值,因此使用这种方式创建的容器中,各个元素的值是不确定的(array 容器不会做默认初始化操作) 2,arrayvalues{}; 将所有的元素初始化为 0 或者和默认元素类型等效的值: 3,当然,在创建 array 容器的实例时,也可以像创建常规数组那样对元素进行初始化:array values { 0.5,1.0,1.5,,2.0}; 这里只初始化了前 4 个元素,剩余的元素都会被初始化为 0.0 array容器成员函数汇总 成员函数 功能 begin() 返回指向容器中第一个元素的随机访问迭代器。 end() 返回指向容器最后一个元素之后一个位置的随机访问迭代器,通常和 begin() 结合使用。 rbegin() 返回指向最后一个元素的随机访问迭代器。 rend() 返回指向第一个元素之前一个位置的随机访问迭代器。 cbegin() 和 begin() 功能相同,只不过在其基础上增加了 const 属性,不能用于修改元素。 cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 size() 返回容器中当前元素的数量,其值始终等于初始化 array 类的第二个模板参数 N。 max_size() 返回容器可容纳元素的最大数量,其值始终等于初始化 array 类的第二个模板参数 N。 empty() 判断容器是否为空,和通过 size()==0 的判断条件功能相同,但其效率可能更快。 at(n) 返回容器中 n 位置处元素的引用,该函数自动检查 n 是否在有效的范围内,如果不是则抛出 out_of_range 异常。 front() 返回容器中第一个元素的直接引用,该函数不适用于空的 array 容器。 back() 返回容器中最后一个元素的直接应用,该函数同样不适用于空的 array 容器。 data() 返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能。 fill(val) 将 val 这个值赋值给容器中的每个元素。 array1.swap(array2) 交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型。 访问array容器中单个元素首先,可以通过容器名[]的方式直接访问和使用容器中的元素,这和 C++ 标准数组访问元素的方式相同,例如: values[4] = values[3] + 2.O*values[1];此行代码中,第 5 个元素的值被赋值为右边表达式的值。需要注意的是,使用如上这样方式,由于没有做任何边界检查,所以即便使用越界的索引值去访问或存储元素,也不会被检测到。(越界无检索) 为了能够有效地避免越界访问的情况,可以使用 array 容器提供的 at() 成员函数,例如 : 2,values.at (4) = values.at(3) + 2.O*values.at(1); 这行代码和前一行语句实现的功能相同,其次当传给 at() 的索引是一个越界值时,程序会抛出 std::out_of_range 异常。因此当需要访问容器中某个指定元素时,建议大家使用 at(),除非确定索引没有越界。(越界可检索) 3,array 容器提供了 data() 成员函数,通过调用该函数可以得到指向容器首个元素的指针 4,在 头文件中还重载了 get() 全局函数,该重载函数的功能是访问容器中指定的元素,并返回该元素的引用。需要注意的是,该模板函数中,参数的实参必须是一个在编译时可以确定的常量表达式,所以它不能是一个循环变量。 重载函数get(): 形式:get(name) n为指定容器元素,name为容器名称 LIST--container: list节点:list节点是一个双向链表,实质是一个模板结构体 template struct _list_node { typedef void* void_pointer; void_pointer prev;//previous void_pointer next; T data; };可见,list的节点是一个以结构体形成的双向链表, 而且是一个环状的双向链表 所以list的节点不要求连续 其中第一个元素的前向指针总为 null,因为它前面没有元素;同样,尾部元素的后向指针也总为 null。 元素和节点的区别:节点是容器(链表)中的一个节点,元素是存储于节点中的数据 list--iterator:源码: list迭代器是一个模板结构体 因为list的节点不要求一定连续,所以不同于vector以指针作为迭代器 list--container:list容器是一个模板类 list的所有的函数,迭代器都是这个模板类的成员 list容器的优点:1,很方便的向容器中插入节点,添加数据值 2,方便删除节点,和数据值,而不会影响其他的节点和数据 list容器的缺点:1,不方便访问节点数据值 list容器的使用场景:需要不断添加,删除,改动元素 list container的成员函数: 1,begin() 2,end() 3,void push_back(const T& x)功能:插入一个节点作为尾节点 实现原理: 4,void push_front(const T& x)插入一个节点作为头节点 和push_back()相对应 5,iterator erase(iterator position)移除迭代器position所指的节点 6,void pop_front()移除头节点 7,void pop_back()移除尾节点 8,void list::clear()清除所有节点(删除整个链表) 9,void list::remove(const T& x)清除数值为x的所有节点 10,void list:: unique()清除数值相同的连续节点,保留一个 list成员函数列表: 表 2 list 容器可用的成员函数 成员函数 功能 begin() 返回指向容器中第一个元素的双向迭代器。 end() 返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。 rbegin() 返回指向最后一个元素的反向双向迭代器。 rend() 返回指向第一个元素所在位置前一个位置的反向双向迭代器。 cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 size() 返回当前容器实际包含的元素个数。 max_size() 返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 front() 返回第一个元素的引用。(相当于返回了第一个元素) back() 返回最后一个元素的引用。 assign() 用新元素替换容器中原有内容。 emplace_front() 在容器头部生成一个元素。该函数和 push_front() 的功能相同,但效率更高。 push_front() 在容器头部插入一个元素。 pop_front() 删除容器头部的一个元素。 emplace_back() 在容器尾部直接生成一个元素。该函数和 push_back() 的功能相同,但效率更高。 push_back() 在容器尾部插入一个元素。 pop_back() 删除容器尾部的一个元素。 emplace() 在容器中的指定位置插入元素。该函数和 insert() 功能相同,但效率更高。 insert() 在容器中的指定位置插入元素。 erase() 删除容器中一个或某区域内的元素。 swap() 交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。 resize() 调整容器的大小。 clear() 删除容器存储的所有元素。 splice() 将一个 list 容器中的元素插入到另一个容器的指定位置。 remove(val) 删除容器中所有等于 val 的元素。 remove_if() 删除容器中满足条件的元素。 unique() 删除容器中相邻的重复元素,只保留一个。 merge() 合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。 sort() 通过更改容器中元素的位置,将它们进行排序。 reverse() 反转容器中元素的顺序。版权声明 本文为[猿饵块]所创,转载请带上原文链接,感谢 https://blog.csdn.net/m0_60274660/article/details/121620466 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |