C++Primer 5th Chap9 Sequential Container
vector | 可变大小数组,支持快速随机访问(在除了尾部之外部分插入删除元素很慢) |
deque | 双端队列,支持快速随机访问(在头尾插入删除元素很快) |
list | 双向链表,仅支持双向顺序访问(在任何位置插入删除元素都很快) |
forward_list | 单向链表,仅支持单向顺序访问(在任何位置插入删除元素都很快) |
array | 固定大小数组,支持快速随机访问,不能插入删除元素 |
string | 仅支持保存字符的类似vector容器 |
tips:通常使用vector是最好的选择,当然如有必要也可选择其他容器
如果不确定使用哪种容器,可以只使用vector和list公共的操作:iterator,无下标,避免随机访问
iterator:
注意:forward_list不支持递减运算符(--)
vector和string的迭代器运算同样支持deque和array
如果begin==end,范围为空(否则范围内至少有一个元素,若干次递增begin可以使得begin==end)
容器类型成员:(详情见Chap16)
需要元素类型,使用容器的value_type
需要元素类型的一个引用,使用reference或const_reference
例如: list<string>::iterator iter;
vector<int>::difference_type count;
begin和end成员:
//显式指定类型 list<string>::iterator it3=a.begin();
//c++11 auto it2=a.begin();或auto it4=a.cbegin();(it4 是const_iterator)
将一个容器初始化为另一个容器的拷贝:(要求容器类型和元素类型必须一致)
#include<list>
#include<vector>
#include<string>
#include<deque>
#include<forward_list>
#include<iostream>
using namespace std;
int main(){
list<string>authors={"Milton","Shakespeare","Austen"};//c++11,列表初始化
vector<const char*>articles={"a","an","the"};
list<string> list2(authors);
forward_list<string>words(articles.begin(),articles.end());//可以将const char*转换为string
deque<string> authList(authors.begin(),it);//假定it是authors的一个元素,拷贝范围:开始到it之前的一个元素
}
只有顺序容器的构造函数才支持大小参数(有时候得自己显式提供初始值),关联容器并不支持
例如:vector<int> ivec(10,-9);(表示10个初始值元素的值都是-9)
标准库容器array:
必须指定固定大小:array<int,80>;
允许对array进行拷贝和对象赋值操作(与内置数组类型不同):
array<int,19> digits=copy;(array<int ,19>copy=/*......*/)
array<int,19> digits=cpy;(int cpy[19]={/*............*/};)
assign允许从一个不同但相容的类型赋值,或者从容器的一个子序列赋值:
list<string> names;
vector<const char*> oldstyles;
names.assign(oldstyles.cbegin(),oldstyles.cend());
swap交换两个相同类型容器的内容(string类型使用swap会使其引用和指针失效,array如果使用swap时间与其元素规模成正比)
swap只是改变了容器的数据结构,元素的值不变(只是指向该元素的容器变了)(array则正好相反)
除了无序关联容器之外的所有容器都支持关系运算符(>,<,>=,<=),只能用于相同类型容器且储存相同类型元素(而且元素本身得支持运算符)
不仅是vector,除了array和forward_list之外,所有顺序容器都支持push_back
注意:容器的元素都是拷贝(与提供该值的对象是谁无关)
list、forward_list、deque还支持push_front,将元素插入到容器头部
vector、deque、list、string还支持insert,在容器的任意位置插入元素(不同容器间的性能差距可想而知)
c++11表示:insert的接受范围或个数的版本返回值为第一个新加入元素的迭代器
例如:list<string> lst;
auto iter=lst.begin();
while(cin>>word)
iter=lst.insert(iter , word);//此举可以一直在头部添加元素
与push_back、push_front、insert对应的,c++11引入的emplace_back、emplace_front、emplace进行的是构造元素(而非拷贝元素)
例如://c保存Sales_data元素
//使用三个参数的Sales_data构造函数,传递给emplace成员函数的参数必需与对象的构造函数参数匹配
c.emplace("23152415215",25,17.99);
//等效地,构建局部临时对象
c.push_back(Sales_data("23152415215",25,17.99));
所有顺序容器都有front成员函数,除了forward_list之外的所有顺序容器都有back成员函数(分别返回首元素和尾元素的引用)
使用这两个函数或者解引用begin和end之前必须确保容器非空
如果希望通过设置变量来改变容器中指定的元素,必须设为引用:
auto &v=c.back(); v=20;(此时通过v改变了c的尾元素的值)
string,vector,array,deque都支持下标运算符(提供快速随机访问)
如果希望确保下标合法,可以使用at成员函数:(如果越界则抛出异常)
vector<string> ivec; cout<<ivec.at(0);(等效于cout<<ivec[0];)
vector和string除了不支持push_front,也不支持pop_front(显而易见的道理)
弹出操作要求容器必须非空(类比front和back函数),返回void(如果弹出的值仍然有用,需要再弹出前对其保存)
搞特殊的forward_list:
改变容器大小:(resize不适用于array)
c.resize(n) | 调整c的大小为n个元素,若n<c.size(),多余的元素被丢弃(如果必须添加新元素,则对新元素进行值初始化) |
c.resize(n,t) | 任何新添加的元素都初始化为t |
resize缩小容器后,被删除的元素的迭代器、引用和指针都失效;对vector、string、deque进行resize操作同样可能使迭代器、引用和指针都失效
在每次添加和删除元素后重新定位迭代器是必要的(旧有的迭代器很可能失效)
不要保存end返回的迭代器,直接使用end迭代器就好(end迭代器调用的很快,也很容易失效)
如:end=v.end();这样的行为常常导致未定义的后果
管理容量的成员函数:(shrink_to_fit只适用于vector、string、deque)
c.shrink_to_fit() | 将capacity()减少为与size()相同大小(只是一个请求,不见得一定实现) |
c.capacity() | 不重新分配内存空间的话,c可以保存的元素数,只适用于vector和string |
c.reserve(n) | 分配至少能容纳n个元素的内存空间,只适用于vector和string(只有需要的空间超过当前容量时才会调用) |
capacity不同于size(好比一瓶水:capacity相当于瓶子大小,size相当于已经装下的水的量)
只有迫不得已之时,容器才能分配新的内存空间
额外的string操作:
unsigned n,len2,pos2;
string s(cp,n);//s是cp(char*类型)指向的数组中前n个字符的拷贝(如果希望完全拷贝cp,要求cp必须以空字符结束:string s(cp);)
string s(s2,pos2);//s是string s2从下标pos2开始的字符的拷贝
string s(s2,pos2,len2)//s是string s2从下标pos2开始len2个字符的拷贝
substr操作:获取原string的一部分拷贝(也可以是全部)
s.substr(pos,n);/返回一个string,从pos开始的n个字符的拷贝(pos默认为0,n默认为pos开始之后的所有字符)
除了标准的insert和erase版本,string还提供了接受下标的版本:
s.insert(s.size(),5,'!');//在s末尾加入5个!
s.erase(s.size()-5,5);//从s删除最后5个字符
string还接受c字符数组(以空字符结尾)的insert和assign版本:
char *cp="Stately,plump Buck"
s.assign(cp,7);//s替换为cp的头七个字符 s=="Stately"
s.insert(s.size(),cp+7);//在s的末尾加入cp第7个字符后面的部分 s=="Stately,plump Buck"
string还接受string的insert版本:
string s="some string", s2="some other string"
s.insert(0,s2);//在s的0位置之前插入s2
s.insert(0,s2,0,s2.size());//在s的0位置之前插入从s2[0]开始到s2.size()的部分
string的特殊函数:append和replace函数
append是在string末尾插入的简写形式:s.append(" sth ");等价于s.insert(s.size()," sth ");
replace是erase和insert的一种简写形式:s.replace(11,5,"Fifth");等价于s.erase(11,5); s.insert(11,"Fifth");(插入的字符串不见得一定与删除的一样长)
string的搜索操作:
6种搜索操作都返回一个string::size_type值,表示匹配发生位置的下标(如果没找到则返回string::npos的static值)
这些string::size_type值都是unsigned类型,所以不适合用带符号类型存储
s.find(args) | 查找s中args第一次出现的位置 |
s.rfind(args) | 查找s中args最后一次出现的位置 |
s.find_first_of(args) | 在s中查找args中任何字符第一次出现的位置 |
s.find_last_of(args) | 在s中查找args中任何字符最后一次出现的位置 |
s.find_first_not_of(args) | 在s中查找第一个不在args中的字符 |
s.find_last_not_of(args) | 在s中查找最后一不在args中的字符 |
args的形式必须是以下之一:
c,pos | 从s中位置pos开始查找字符c,pos默认为0 |
s2,pos | 从s中位置pos开始查找字符串s2,pos默认为0 |
cp,pos | 从s中位置pos开始查找c字符数组cp(以空字符结尾),pos默认为0 |
cp,pos,n | 从s中位置pos开始查找c字符数组cp(一空字符结尾)的前n个字符,pos和n无默认值 |
#include<string>
#include<iostream>
using namespace std;
int main(){
//一种常见的查找模式
string numbers(""),name("r2d2");
string::size_type pos=;
while((pos=name.find_first_of(numbers,pos))!=string::npos){
cout<<"found number at index: "<<pos
<<" element is "<<name[pos]<<endl;
++pos;
}
}
string的compare函数:
s.compare(args);根据s比另一个string等于、大于、小于,返回0,正数,负数。
args的几种形式;
s2 | 比较s和s2 |
pos1,n1,s2 | 将s中从pos1开始的n1个字符与s2比较 |
pos1,n1,s2,pos2,n2 | 将s中从pos1开始的n1个字符与s2中从pos2开始的n2个字符比较 |
cp | 比较s和cp(cp是c字符数组,以空字符结尾) |
pos1,n1,cp | 将s中从pos1开始的n1个字符与cp比较 |
pos1,n1,cp,n2 | 将s中从pos1开始的n1个字符与cp中的前n2个字符比较 |
string的数值转换:
容器适配器:
标准库定义了3个顺序容器适配器:stack、queue(此二者基于deque实现)、priority_queue(基于vector实现)
适配器的拷贝操作:
deque<int>deq={/*..................*/};
stack<int> stk(deq);//从deq拷贝元素到stk
stack适配器可由除了array和forward_list之外的其他容器进行构造,queue可由list和deque构造,priority_queue可由vector和deque构造
这些适配器的使用与数据结构课上自己写的结构的使用方法一样,而且比自己写的性能更好
C++Primer 5th Chap9 Sequential Container的更多相关文章
- Sequential Container
Notes from C++ Primer Initialize container by iterator When copy a container to another, the contain ...
- C++Primer 5th 练习 12.19
这阵子真是太忙了, 连续做了四个课设. 当然这并不能作为好久没写博客的借口, 没写博客的主要原因只有一个: 懒. 最近又开始回顾C++的语法与特性(据说C++就是一门需要反复回顾的语言),以及学习C+ ...
- 【读书笔记】C++ primer 5th 从入门到自闭(一)
这几天看了C++ primer 5th的一二章,有很多收获,但是有的地方因为翻译的问题也搞得理解起来颇为难受啊啊啊啊.尤其是const限定符,在C语言并没有这么多复杂的语法,在C++里面语法细节就多的 ...
- C++ Primer 5th 第1章 开始
*****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...
- c++ primer 5th 练习3.43
#include <iostream> using namespace std; int main() { ][]={,,,,,,,,,,,}; /* for(int (&i)[4 ...
- C++ Primer 5th 第16章 模板与泛型编程
模板是C++中泛型编程的基础,一个模板就是创建一个类或者函数的蓝图或者说公式. C++模板分为函数模板和类模板. 类模板则可以是整个类是个模板,类的某个成员函数是个模板,以及类本身和成员函数分别是不同 ...
- C++ Primer 5th 第15章 面向对象程序设计
面向对象程序设计的核心思想是:数据抽象.继承和动态绑定. 数据抽象:将类的接口与实现分离: 继承:定义相似类型并对相似关系建模: 动态绑定:一定程度上上忽略相似类型间的区别,用同一方式使用它们. 1. ...
- C++ Primer 5th 第13章 拷贝控制
当一个对象的引用或者指针离开作用域时,析构函数不会执行. 构造函数有初始化部分(初始化列表)和函数体. 析构函数有析构部分和函数,但析构函数的析构部分是隐式的.
- C++ Primer 5th 第12章 动态内存
练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...
随机推荐
- linux下redis的安装、启动、关闭和卸载
edis 在Linux 和 在Windows 下的安装是有很大的不同的,和通常的软件安装是一样的. 一 下载 Redis 安装包 去redis 官网下载reids 安装包, redis 官网默认只提 ...
- python 时间等待
#coding=utf- import time t1=time.time() time.sleep() t2=time.time() print(t2-t1) 输出 3.00304102898
- zabbix(4)数据库表分区优化
一.zabbix 数据库存储 zabbix-server将采集到的数据存储在数据库(mysql.oracle等),而数据存储的大小与每秒处理的数量量有关,因此数据存储取决于以下两个因数: (1)Req ...
- PHP + CI框架 + AdminLITE权限管理系统
源码地址:https://github.com/yangsphp/rbac-master
- vue-qr生成下载二维码
安装vue-qr npm install vue-qr --save 生成二维码实列 <vue-qr ref="Qrcode" :text="qrCodeConfi ...
- spring bean 的作用域之间有什么区别
spring bean 的作用域之间有什么区别? spring容器中的bean可以分为五个范围.所有范围的名称都是说明的, 1.singleton:这种bean范围是默认的,这种范围确保不管接受到多个 ...
- 基于Spring框架怎么构建游戏玩法服务
说明:本篇阐述的问题,是基于前面的游戏服务器架构设计的. 问题 众所周知,Spring最擅长的领域是无状态服务的构建,而游戏(尤其是玩法部分)是有状态的.以棋牌游戏为例,玩法服务里面大概涉及以下两类对 ...
- EL表达式 与 JSTL标准标签库
目录 EL表达式 什么是EL表达式 作用 EL内置11对象 EL执行表达式 JSTL 什么是JSTL JSTL标准标签库有5个子库 把JSTL标签库jar包引入工程当中 if标签 foreach标签 ...
- 安卓APP在线升级
安卓APP在线升级 通过IDHTTP组件在线下载APP到手机中,然后自动安装这个APP程序. 1)在线下载APP程序 需引用单元: {$IFDEF ANDROID} FMX.Helpers.Andro ...
- Hallelujah Leonard Cohen
Hallelujah 歌词 Leonard Cohen Now I've heard there was a secret chord 我听说有一个隐秘的弦音 That David ...