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 ...
随机推荐
- 微信小程序入门与实战 常用组件API开发技巧项目实战*全
第1章 什么是微信小程序? 第2章 小程序环境搭建与开发工具介绍 第3章 从一个简单的“欢迎“页面开始小程序之旅 第4章 第二个页面:新闻阅读列表 第5章 小程序的模板化与模块化 第6章 构建新闻详情 ...
- php发现一个神奇的函数
echo strtr('aaddffvvbbcc','avc','242'); //22ddff44bb22 echo '<br>'; echo str_replace('ad',22,' ...
- Wamp 升级php7.3报错
电脑系统:win10 Wamp版本: WampServer Version 3.0.4 32bit Apache 2.4.18 - PHP 7.3.7 - MySQL 5.7.11 PHP 5.6.1 ...
- React拾遗(下)
reconciliation(协调算法) react用于更新DOM的算法.基于两点假设,实现了一个启发的O(n)算法: 两个不同类型的元素将产生不同的树. 通过渲染器附带key属性,开发者可以示意哪些 ...
- android studio: 让项目通过阿里云 maven jcenter 下载依赖资源
打开项目根目录下的 build.gradle(Project:项目名称一级的gradle),如下所示添加阿里 maven 库地址: // Top-level build file where you ...
- VS2017调试程序时 无法启动web iis或者提示ID为***的进程未启动
打开项目的.csproj文件,定位到<WebProjectProperties>,把关于IIS的配置<DevelopmentServerPort>.<Developmen ...
- ISO/IEC 9899:2011 条款5——5.2.1 字符集
5.2.1 字符集 1.两个字符集和它们相关联的依次顺序应该被定义:写在源文件中的集合(源字符集),以及在执行环境中被解释的集合(执行字符集).每个集合此外被划分为一个基本字符集,其内容由本子条款给出 ...
- Oracle查看表结构的方法【我】
Oracle查看表结构的方法 方法一: 在命令窗口下输入 DESC table_name; 回车 方法二: 在sql窗口下 SELECT DBMS_METADATA.GET_ ...
- IfcAxis2Placement3D IFC构件的位置和方向
IfcAxis2Placement3D定义了三维空间中物体的位置和方向,由三部分组成: The attribute Axis defines the Z direction, RefDirection ...
- 17flutter中的路由/命名路由/命名路由传值/无状态组件传值/有状态组件传值。
main.dart import 'package:flutter/material.dart'; import 'package:flutter_demo/pages/Search.dart'; i ...