STL标准模板库

一.容器,算法与迭代器

1、概念

STL(标准模板库)_stl库-CSDN博客

为了简历数据结构和算法的一套标准,并且降低他们之间的耦合关系,以提升各自的独立性、弹性、交互操作性(相互合作性,interoperability),诞生了STL

我们使用末班编程可以将函数或类进行模板化,让他们更具有通用性

2.函数模板

2.1函数模板

语法:函数模板就是建立一个通用的函数,它的返回值类型、参数类型可以不具体指定,用一个 虚拟的类型表示,也就是泛型

定义:template<typename T> 或 template<class T> T为变量名,可改变

函数声明:在方法或者类上面声明后才是模板

函数模板使用的两种方式:1.自动推导泛型类型 2.手动指定泛型的类型

2.2模板函数的注意事项:

自动类型推导,必须推导出一致的类型T,才可以使用

模板必须要确定出T的类型,如果不能自动推导出来,需要我们手动指定类型

2.3普通函数和函数模板的区别:

普通函数调用是可以发生自动类型转换(隐式类型转换)

函数模板使用时,如果利用自动类型推导,不会发生隐式类型转换。除非手动指定T的类型

注:*** 建议使用手动指定T类型的方式来调用函数模板

2.4普通函数和模板函数的调用规则:

如果普通函数和模板函数同名了,优先调用普通函数(普通函数是具体类型的实现)

如果非要调用模板函数,可以增加一个空的模板参数列表<>来指定函数模板

如果函数模板可以更好的匹配,如参数更匹配,如果提供了模板函数,就最好不要再定义了。

2.5模板的局限性:

这些情况下,不能使用模板,如果传入的参数不是基本类型,而是数组或对象等自定义的类型, 则不能用数组。也就是T的类型是对象自定义类型,需要使用特定的模板解决这个问题,特定 模 板其实也是模板的一个重载,需要使用template<>来指定这是个特定模板。放在函数变量返回值前面,如下。

注意:特定模板,template<>开头,放到模板函数前面,特定模板会优先调用

3.类模板

3.1类模板语法:

类模板的作用是建立一个通用类,类的成员数据类型可以不具体指定,用泛型来代替。

类模板和函数模块的区别主要有两点:

1.类模板没有自动类型推导的用法,只能手动指定泛型的类型。

2.类模板在模板参数列表中可以有默认参数

语法:template<class T>

3.2将类模板的对象作为函数参数

三种方式传参:

1.手动指定模板的类型(推荐)

2.把参数模板化

3.把整个类模板化

3.3类模板遇到继承:

如果父类是模板类,子类继承父类,有两种方式:

1.指定了父类的具体类型,子类可以是普通类,也可以是模板类

2.父类和子类都是模板类,继承的时候可以不指定父类的泛型类型,但是指定了子类的泛型类 型。这时候父类会具有跟子类泛型一样的类型。

总结:

类模板跟函数模板不同的地方,他不会自动推导,必须指定类型

类模板作为参数传入的时候有三种方式:推荐第一种

类模板与继承都存在时:注意这两种情况

4、六大组件

六大组件:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

1.容器:存放数据

2.算法:操作数据

3.迭代器:算法 只能借助迭代器 操作容器数据

4.仿函数:为算法提供更多的策略

5.适配器:为算法提供更多参数的接口

6.空间配置器:为算法和容器动态分配、管理空间

STL的一个重要特性是将数据和操作分离。数据由容器类别加以管理,操作由特定的算法完成。

容器和迭代器是一 一对应的(每个容器的结构不一样)

算法分为:质变算法和非质变算法

质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝、替换、删除等等

非质变算法:是指运算过程中不会更改区间内的元素内容,例如:查找、计数、遍历、寻找极值等等

5、string类

5.1string容器基本概念

Char风格字符串(以空字符('\0')结尾的字符数组)太过复杂难以掌握,所以C++标准库定义了一中string类,定义在头文件。

string和Char风格字符串对比:

Char * 是一个指针,String是一个类

string封装了char* ,管理这个字符串,是一个char型的容器

string封装了很多使用的成员方法

find查找,copy拷贝,delete删除,替换replace,插入insert

不用考虑内存释放和越界

string管理char*所分配的内存。每一次string的赋值,取值都由string类负责维护,不用担心复制越界和取值越界等。

5.1.1 string构造函数

string(); // 创建一个空的字符串 例如:string str;

string(const string& str) // 使用一个string对象初始化另一个string对象

string(const char* s) // 使用字符串s初始化

string(int n,char c); // 使用n个字符串c 初始化v

5.1.2 string基本赋值操作

重载:

string& operator= (const char* s); // char*类型字符串赋值给当前的字符串

string& operator=(const string &s); // 把字符串s赋值给当前的字符串

string& operator=(char c); // 字符赋值给当前的字符串

赋值:

string& assign(const char *s); // 把字符串s赋给当前的字符串

string& assign(const char *s,int n); // 把字符串s的前n个字符赋值给当前的字符串

string& assign(const string &s); // 把字符串s赋给当前字符串

string& assign(int n,char c); // 用n个字符c赋给当前字符串

string& assign(const string &s,int start ,int n); //将s从start开始n个字符赋值给字符串

拼接:

重载 += 运算符:

string& operator+=(const char* s); // 把运算符右边的字符串拼接到左边的字符串后面

string& operator+=(char c); // 单个字符拼接

string& operator+=(const string& str); // string字符串的拼接

append函数:

string& append(const char* s); // 字符串常量s拼接到当前字符串结尾

string& append(const char* s,int n); // 把字符串s的前n个字符拼接到当前字符串结尾

string& append(const string& s); // 把string字符串拼接到当前字符串结尾

string& append(const string& s,int pos,int n); // position缩写pos,代表位置(位置下标/指针). 从s字符串的pos位置开始选择n个字符,拼接到当前函数string后面

查找和替换

string查找和替换:

查找:在string字符串中查找指定的字符串是否存在,找到返回对应位置,找不到返回-1

替换:在指定的位置替换字符串。

从左往右查找:find

int find(const string& str,int pos=0) const; // 查找字符串str,返回第一次出现的位置,从pos位置开始查找,pos默认值是0

int find(const char* s,int pos=0) const; // 查找字符串s第一次出现的位置,从pos开始查找

int find(const char* s,int pos=0,) const; // 从pos位置查找字符串s的前n个字符第一次出现的位置

int find(const char c,int pos=0) const; // 从pos开始查找字符c第一次出现的位置

从右往左查找:rfind

int rfind(const string& str,int pos=npos) const; // 从右往左开始查找str最后一次出现的位置,

从pos开始查找,pos默认值是npos,npos是string类的静态属性, npose最后一个

int rfind(const char* s,int pos=npos) const; // 查找字符串s最后一次出现的位置,从pos开始查

int rfind(const char* s,int pos=npos,int n) const; // 从pos查找s的前n个字符最后一次出现的位置

Int rfind(const char c,int pos=npos) const; // 从pos开始查找字符c最后一次出现的位置

替换:replace

string& replace(int pos,int n,const string& str); // 替换从pos开始的n个字符为字符串str

string& replace(int pos,int n,const char* s); // 替换从pos开始的n个字符为字符串s

用于字符串之间的比较,比较的是ASCII码,比较是否相等。

= 返回0 > 返回1 < 返回-1

int compare(const string& s) const; // 调用compare函数的字符串与参数字符串s比较

int compare(const char* c) const

重载运算符[];

char& operator[](int n); // 通过下标取字符

通过函数取值at;

char& at(int n); // n是下标

插入:

string& insert(int pos,const char* s);// 从pos位置插入字符串s

string& insert(int pos,const string& str); // 从pos位置插入字符串str

string& insert(int pos,int n,const char* c);// 从pos位置插入n个字符c

删除:

string& crase(int pos,int n=npose); // 删除从pos开始的n歌字符

从字符串中截取想要的子串

string substr(int pos,int n=npose) const; // 返回从pos开始的n歌字符组成的字符子串

9、vector类

vector 动态数组

9.1 基本概念

vector是STL的容器,这种数据结构和数组类型,但它本质上是个类,vector也叫单端数组(一端开 口),vector是动态的,空间可以动态扩展,数组时静态的。

vector如何动态扩展:

当空间不足的时候,vector会重新申请一块更大的空间,将旧空间的数据拷贝到新空间,旧空间被释放掉。

vector有两个和空间大小相关的参数:capacity容量和size元素个数

例:纸箱可以放50个苹果,实际你放了40个,40就是size,50是capacity, 如果要放60就得用更大箱子,那就得重新拿一个更大的箱子,然后把之前小箱子的苹果放进大箱子,小箱子被回收。 (动态扩展的过程是自动发生的,不需要我们手动操作。)

9.2 构造函数

vector<T> v; // 用模板来实现的类,构造函数

vector<T>(v.begin(),v.end()); // 将一个vector的指定区间的元素拷贝给当前的vector(区间是左闭右开) [v.begin(),v.end()),end不取

vector<T>(n,elem); // 将n个元素拷贝给当前vector

vector<T>(const vector& v); // 拷贝构造函数,把当前vector的元素拷贝到v里面

9.3 赋值函数

vector& operator=(const vector& v); //重载赋值运算符assign函数来赋值:

assign(beg,end); // 将参数vector[beg,end)区间中的元素拷贝给当前vector。

assign(n,elem); // 将n个元素拷贝给当前vector。

9.4 容量和大小

empty(); // 判断容器是否为空

capacity(); // 返回容器的容量

size(); // 返回容器中元素的个数

shrink_to_fit(); //缩容的函数

resize(int num); // 重新指定容器的size为num,注意只改变size,不影响capacity.如果size变长,比实际元素多了,那就以默认值填充。如果size变短,比实际元素少,则末尾超出size的元素就会被删除。

resize(int num,element); // 跟上面函数一样,区别是默认值位置,可以指定填充的元素

9.5 插入和删除

尾部操作(建议的,因为尾部开口,效率高):

push_back(ele); // 尾部插入元素ele

pop_back(); // 删除最后一个元素

插入insert(不建议,因为会影响到其他元素们还要重新排列,效率低)

insert(iterator pos,ele); // 在迭代器iterator指向的Pos位置插入元素ele,返回迭代器指针

insert(iterator pos,int count,ele); // 迭代器指向位置pos处插入count个元素ele

删除erase:

erase(iterator pos); // 删除迭代器指向的pos位置的元素

erase(iterator start,iterator end); // 删除start到end之间的元素

clear(); // 删除所有元素

9.6 数据存取

运算符[]重载,返回下标所在的数据

at(int idx); // 返回下标所在的数据

front(); // 返回容器中第一个元素

back(); // 返回最后一个元素

9.7 互换函数

可以实现两个vector互换各自的元素

swap(vec); //当前vector和参数vec互换元素

利用互换实现一个容器的缩容,resize无法改变容器capacity的大小。可以先resize,然后再跟另一个容器互换,达到改变capacity目的。

9.8 预留空间

通过提前预留出容器的空间,以减少vector在空间不足的时候进行动态扩展的次数。

reserve(int len); // 容器预留len个元素长度的空间,注意:预留的位置不初始化,所以不可访问。

如果需要保存大量数据,可以提前预留足够的空间,减少动态扩展的次数。

9.9 几个常用的算法(需要引入头文件#include<algorithm>)

排序:sort

sort(iterator beg,iterator end); // 对beg和end区间的元素进行排序,默认从小到大

sort(iterator beg,iterator end,func); // 对beg和end区间的元素进行排序,按照func函数指定 的方式排序

反转:reverse

reverse(iterator beg,iterator end); // 对beg和end区间的元素进行反转

复制:copy

copy(源头的起始位置,源头的结束位置(不包括),目标的起始位置); // 左闭右开区间,选取元容器的一段内容复制到目标容器的起始位置

查找:find

find(iterator beg, iterator end, ele); // 在beg和end区间查找元素ele,如果找到返回迭代器位置,找不到返回end迭代器(最后)

10、deque双端队列(两端开口)

10.1 基本概念

双端数组,就是两端都开口,跟vector很像,也是类模板,可以很搞笑地对两端进行操作

deque和vector的区别:

vector是单端开头的连续性空间,deque是双端开口的连续性空间。它解决了vector在头部操作 效率很差的问题。

deque是没有容量的,因为是两端开口,两边都可以随时加数据,它是以分段的连续空间组合而 成的,随时可以增加一段新的空间链接起来,它不会像vector那样因为空间不足而重新申请 一块更大的空间。

deque内部的工作原理:

deque是分段连续的空间,内部有个中控器,负责维护每段缓冲区中的内容,而缓冲区才是真正放数据的区域。

中控器维护的每个缓冲区的地址,使得deque像一片连续的内存空间。

deque的特性:

双端插入和删除的效率高(推荐)

insert指定位置插入也会导致数据移动,效率低(不推荐)

deque和vector一样,都支持随机访问,都可以通过下标或者at取值

10.2构造函数

deque<T> deq; // 无参构造

deque<T> deq(beg,end); // 将参数deque[beg,end) 区间中的元素拷贝给当前deque

deque<T> deq(n,ele); // n个ele来构造

deque<T> deq(const deque& deq); // 拷贝构造

10.3赋值函数

重载赋值运算符 =

assign(beg,end);//将参数deque[beg,end)区间中的值完成对当前deque的赋值

assign(n,ele);//n个ele完成赋值

10.4 大小相关函数

empty(); // 判断是否为空

size(); // 返回元素个数

resize(int num); // 重新指定元素个数,如果变长默认值填充新位置,如果变短元素被删除 resize(int num,ele); // 重新指定元素个数,如果变长用ele填充新位置,如果变短元素被删除

10.5插入和删除

push_back(ele); // 尾部插入一个元素

push_front(ele); // 头部插入一个元素

pop_back(ele); // 尾部弹出(删除)一个元素

pop_front(ele); // 头部弹出(删除)一个元素

指定位置:

insert(pos,ele); // 在pos位置插入ele

insert(pos,n,ele); // 在pos位置插入n个ele

insert(pos,beg,end); // 在pos位置插入参数deque的beg到end之间的元素

删除:

erase(pos); // 删除pos位置数据

erase(beg,end); // 删除beg到end区间的数据

clear(); // 清空

10.6数据存取,支持随机存取

at(int idx);

[]

front();//取第一个元素

back();//取最后一个元素

10.7相关算法:引入#include<algorithm>

排序:

sort(beg,end); // 区间内排序,升序

sort(beg,end,func); // 区间内排序,使用func指定的规则,func要自己写一个排序的函数

reverse(beg,end); // 区间内反转

copy(源beg,源end,目标beg); // 把源beg,源end复制到目标里面

find(beg,end,ele); // 区间内找ele,若找到返回他的位置,若找不到返回end的位置(因为end是取不到的,左闭右开)

11.stack栈(先进后出)

11.1基本概念

stack是一种先进后出的数据结构,它只有一个出口,并且我们只能操作这个出口。stack采用类模板实现。

stack只允许在出口处(也就是栈顶)来操作,可以新增元素、删除元素、可以获得栈顶元素,其他位置都不可访问,不可以存取。

所以stack不具有遍历行为,也没有迭代器,不支持随机访问,不能使用[]或at来取值。

栈的术语:

栈顶(操作端,出口),栈底(最开始的数据)。入栈:栈顶存入数据,出栈:栈顶删除数据。

11.2stack构造函数

构造函数:

stack<T> stk; // 无参构造

tack<T> stk(const stack& stk); // 拷贝构造

赋值操作:

重载赋值运算符 =

数据存取:

push(ele); // 向栈顶添加元素

pop(); // 移除栈顶的元素

top(); // 返回栈顶元素

大小:

size(); // 返回栈的大小,元素个数

empty(); // 判断是否为空

12.单端队列(先进先出,有出口有入口)

12.1基本概念:

queue是一种先进先出的数据结构,它有两个口,队头和队尾,队尾只能进,队头只能出。也是类模板。

只能在队尾新增元素,队头移除元素,只有队头和队尾的元素可以访问,其他元素不可访问,不具有遍历行为,没有迭代器,

不支持随机访问,不能[] 从队尾进数据叫入队,从队头出数据叫出队。

12.2queue常用函数:

构造函数:

queue<T> que; // 无参构造

queue(const queue& que); // 拷贝构造

赋值函数:

重载运算符 =

数据存取:

push(ele); // 队尾添加数据,入队

pop(); // 队头删除第一个元素

back(); // 返回队尾的最后一个元素

front(); // 返回队头第一个元素

大小:

empty(); // 判断是否为空

size(); // 返回queue的元素个数

13.list容器

13.1 基本概念

list是物理上非连续的存储结构。数据元素的逻辑顺序是通过链表中的指针链接实现。

链表组成:链表是有多个节点构成的。一个节点是由数据域和指针两部分构成。

由于存储方式不是连续的空间,所以List的迭代器只支持前移一位和后移一位。

链表也是采用动态内存分配的,不会造成浪费或者溢出。

链表插入和删除十分迅速,不会影响其他元素。

链表的缺点是遍历的时候耗费大,时间和空间都有耗费。

list和vector是我们常用的两种容器,比较一下它们:

vector必须先定义一个容量,它不适应动态增减频繁的情况,会频繁重新申请空间,或者造成空间浪费

list是动态分配内存的,可以适应数据增减频繁的情况,不会影响其他数据,而且插入和删除很快。

13.2 list构造函数

list<T> lst;

list<T> lst(beg,end); // 将list[beg,end)区间中的元素拷贝给当前list

list<T> lst(n,ele); // 使用n个ele构造

list<T> lst(const list& lst); // 拷贝构造

13.3 list赋值和交换

重载赋值运算符 =

assign(beg,end); // 将参数list[beg,end)区间中的元素赋值给当前List

assign(n,ele); // 将n个ele赋值给当前list

swap(lst); //交换两个list得元素

13.4 大小

size(); // 返回元素个数

empty(); // 判断是否为空

resize(int num); // 重新指定元素个数,如果变长默认值填充新位置,如果变短元素被删除

resize(int num,ele); // 重新指定元素个数,如果变长用ele填充新位置,如果变短元素被删除

13.5 list插入和删除

push_back(ele); 尾部插入一个元素

pop_back(); 尾部弹出(删除)一个元素

push_front(ele); 头部插入一个元素

insert(pos,ele);

insert(pos,n,ele);

insert(pos,beg,end);

erase(beg,end);

erase(pos);

clear();

remove(ele); // 删除所有与ele相同的元素

13.6 list存取

首先不支持随机存取,[]和at不能用

front(); // 返回第一个元素

back(); // 返回最后一个元素

13.7 list反转和排序(不是算法,是list的成员函数)

reverse();//反转list

sort();//list排序,默认升序

14.set和multiset

14.1概念

二者类似于集合:set(元素不允许重复)、multiset(元素可以重复),set/multiset都会给元素自动排序

set/multiset 也是类模板,它们内部的数据结构是以(红黑树)来实现的。

树的介绍:

1.二叉树

二叉树:数的任何节点最多只能由两个子节点,这两个节点称为左节点和右节点。

2.二叉搜索树

二叉树中的节点按照一定规则进行排序,对元素的访问效率就会提高。规则:任何节点的元素值一定大于其左子树中的每个节点的值,并且小于其右子树所在的每个节点的值。

因此,从根节点一直往左走到头就是最小值,一直往右走到头就是最大值

3.平衡二叉树

当一个二叉搜索树左右子树的层级相差太多的时候,那么搜索层级深的子树的话费时间肯定大于层级浅的子树,层极差的越多时间相差越大,

不利于提高搜索效率,所以把节点数据重新排列,让左子树和右子树的层级只差不大于1,也就是最多差一层,这就叫平衡二叉搜索树。

4.红黑树

为了提高查询效率,把节点分为红色节点和黑色节点,这样就得到了红黑树。

4.1 节点有红色和黑色两种

4.2 根节点是黑色的。

4.3 红节点的两个子节点都是黑节点

4.4 对于任何一个节点,从该节点到它的所有后代节点的简单路径上,包含的黑节点数量是一样的。

4.5 红黑树的所有叶子节点都是黑色的,叶子节点是空节点。

14.2set构造和赋值

set<T> st;

set<T> st(const set& s);

重载运算符 =

14.3set插入和删除

insert(ele); // 插入元素,会自动排序

erase(pos); // 删除迭代器指向位置的元素

erase(beg,end); // 删除beg到end之间的元素

erase(ele); // 删除指定元素

clear(); // 清空

14.4set大小和交换

size(); // set集合的大小

empty(); // 集合是否为空

swap(st); // 交换集合

14.5set查找和统计

find(ele); // 查找某个元素,如果有则返回该元素迭代器位置,没找到返回末尾位置(用是
不是末尾位置判断)

count(ele); // 判断这个元素个数,结果返回0/1

注意:不能修改set元素的值。因为set是红黑树,树(左子树比节点小,右子树比节点小)
排序规则,改变固定位置元素的值,会破坏树的数据结构。

14.6set和multiset的区别

set元素不能重复;multiset元素可以重复,它不会做元素的检查。

14.7pair对组

用于创建成对的数据

创建方式:

pair<type,type> p(key,value);

pair<type,type> p=make_pair(key,value);

访问方式:

使用对组的两个属性:first和second

set练习:

15.map和multimap

15.1基本概念

map中所有元素都是键值对存在的(key,value),key不允许重复,通过key(类似于索引)来进行,map的数据结构基于红黑树,通过map[key]的方式拿到key对应的value

map和multimap区别:

map不允许key重复

multimap允许重复

15.2map的构造、赋值、插入、删除

map<T1,T2> mp;

map<T1,T2> map(const map& mp);

重载运算符 =

insert(ele); // ele是对组

clear(); // 清空

erase(pos);

erase(beg,end);

erase(key); // 通过key来删除元素

15.3map的取值

可以使用map[key]方式拿到这个key对应的value

15.4map的大小和交换

size();

empty();

swap();

15.5map的查找和统计

find(key); // 按K查找,存在返回迭代器位置,不存在返回end迭代器位置

cout(key); // 统计Key元素个数,对于Map来讲,结果0/1

15.6multimap

key可以重复,其他函数同上

无法通过key取值

可以通过使用cout和find,找出有几个相同的key的元素,找到后迭代器会把相同的key存放在一起,找到第一个重复的key的位置,就能拿到后面每个重复的Key,通过对迭代器指针的++操作就可以拿到后面的元素。

16.容器总结

16.1容器总结

各种容器的共性:

STL提供的都是值value的操作,而不是引用,当容器插入元素的时候,容器内部就完成了拷贝动作,真正拷贝了一份元素到容器中。

去了stack栈和queue单端队列,其他容器都提供了迭代器函数,比如begin()和end(),可以通过迭代器访问元素

每个容器都提供了一个默认的构造函数和拷贝构造函数,都有size和empty函数。

不同容器的使用场合:

容器使用的业务场景:

1.vector适合存储历史操作记录,如日志,历史记录一般不删除,只查看和新增

2.deque适合排队业务,头部的数据快速移除,尾部的快速添加

3.list适合数据的频繁插入和删除,并且不确定位置。但不是和做遍历

4.set适合需要排序的数据,并且数据不重复。比如说游戏英雄排行榜

5.map适合存储成对出现的数据,数据查询效率也很高。如:用户的信息id和姓名

id作为key,姓名作为value。树的结构适合做查找。

16.2仿函数(函数对象)

函数对象本质上是个类,只是类似于函数

函数的用法:

他有函数的运算符(),像是调用,但是类内部重载了(),有operator函数

仿函数主要是当作参数来传递,用于指定容器的排序规则,容器内部如果自定义类型数据和对象的时候,需要我们手动指定排序规则才可以。

谓词:仿函数返回值是bool类型的。谓词还可以根据参数不同叫一元二元谓词。一元指一个参数。

系统提供了一些写好的仿函数,引入头文件#include<functional>即可使用

有三类:

算数仿函数:加法plus、减法minus、乘法multiplies、除法divides、取反negate

关系仿函数:等于equal_to、不等于not_equal_to、大于greater(可以降序)、小于less(升序)、大于等于greater_equal

逻辑运算:逻辑与logical_and、逻辑或logical_or、逻辑非logical_not

16.3STL常用算法:需引入#include<algorithm>

遍历:

for_each(beg,end,func); // 遍历符合func方法的容器内的元素

查找:

find(beg,end,ele); // 在beg到end区间找ele元素

find_if(beg,end,func); // 在beg到end区间找到符合func方法条件的元素

count(beg,end,ele); // 在beg到end区间内统计ele元素的数量

count_if(beg,end,func); // 在beg到end区间统计满足func方法的数量

排序:

sort(beg,end,func); // 按照func规则排序

random_shuffle(beg,end); // 对范围内元素随机洗牌

reverse(beg,end); // 对范围内元素反转

拷贝和替换:

copy(beg,end,目标迭代器位置);

replace(beg,end,oldvalue,newvalue); // 把区间内的旧值换成新值

replace_if(beg,end,func,newvalue); // 把区间内满足func函数的值换成新值

swap(容器1,容器2); // 互换容器的元素

关于集合的算法:交集、并集、差集:

set_intersection(beg1,end1,beg2,end2,目标集合的迭代器位置); // 交集

set_union(beg1,end1,beg2,end2,目标集合的迭代器位置); // 并集

set_difference(beg1,end1,beg2,end2,目标集合的迭代器位置); // 差集

16.4区别:

有迭代器:

1.vector(单端数组):有capacity,

2.deque(双端数组),有中控器,管理分段存储的数据

3.list(物理上非连续的存储结构,链表)

4.set(红黑树),元素不允许重复

5.map(map中的元素都是对组pair,key和value)

无迭代器:

1.stack(栈)先进后出

2.queue(队列)先进先出

二、C++11新特性

1.自动类型推导auto

1.1auto初始化

C++11之前auto用来指明变量的存储类型,它和static 相对,所以省略了

C++11之后,auto做自动类型的推导。编译器会自动推导出变量类型,但是编译的时候还是会把auto替换成真正的变量类型。

语法:

autoname = value; // 会根据value的值自动推导name变量的类型

注:用auto必须马上赋初值,不然没有推导。

1.2auto的使用限制

auto不能在函数参数中使用,因为函数参数只有在调用函数的时候才给参数赋值,而auto要马上赋值

auto不能用于类的属性

auto不能用于定义数组

auto可以作为函数的返回值使用,但是只能在函数定义的时候使用auto作为返回值,函数声明的时候不能用。

auto不能作为模版参数。如:vector<int> 不能写成vector<auto>

1.3auto的使用场合

定义变量的时候立刻给变量赋值

用于循环语句中循环变量的定义并且马上赋值

用于容器迭代器的时候,使用auto方便

2.空指针nullptr

C++11引入nullptr关键字充当空指针。这个空指针可以隐式转换成 任意类型的指针,可以进行任意类型的比较,但它不能跟int比较。同时0仍然作为空指针使用。

3.lambda表达式

3.1语法:

lambda表达式也叫lambda函数,匿名函数,没有函数名。

[捕捉列表](参数)mutable->返回值类型[函数体]; mutable可变的意思

[捕捉列表]:

位于起始位置,可以捕捉当前作用域的变量,供lambd函数使用

[]:不捕捉任何变量,但仍然可以使用全局变量和静态变量

[变量a,变量b,...]:捕捉外部的变量a,b,... 同时默认的捕捉方式是值传递的方式

[=]:所有捕捉的变量都是用值传递的方式,包括this指针

[&a]:以引用传递的方式捕捉变量,包括this指针

[&]:所有捕捉的变量都是用引用传递的方式,包括this指针

[this]:以值传递的方式使用this指针

****可以连用如:[=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量

参数:

跟普通函数的参数列表使用相同,如果不需要传参,()可以省略

mutable:

默认情况下,匿名函数总是一个const函数,所以捕捉的变量是不能修改的,使用mutable修饰后,就可以修改原变量的值,取消了const特性。

注意:如果使用了mutable,()不能省略,即使没有参数

->返回值类型:

代表匿名函数的返回值类型,如果没有返回值可以省略。如果返回值类型是明确的类型,也可以省略,让它自动推导。

[函数体];

函数体内可以使用捕捉来的变量,也可使用定义的参数。

4.for范围遍历

4.1for范围遍历C++11的新遍历方式

for(变量类型 变量名: 集合)

{

循环体;

}

变量的类型要和序列中的元素类型保持一致,我们可以使用auto来自动推导

序列可以是数组、容器等等

4.2for范围遍历和传统for循环遍历的区别:

for范围遍历无法指定遍历的次数,只能全部遍历完

4.3for范围遍历和传统for循环遍历的区别:

for范围遍历无法指定遍历的次数,只能全部遍历完

for范围遍历还可以再遍历的时候用引用的方式指定变量,达到修改原值的效果

for范围遍历在遍历字符串时,会一致遍历到字符串结束标志'\0'

5.初始化列表
6.只能指针
7.类型别名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jason 斯坦森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值