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的更多相关文章

  1. Sequential Container

    Notes from C++ Primer Initialize container by iterator When copy a container to another, the contain ...

  2. C++Primer 5th 练习 12.19

    这阵子真是太忙了, 连续做了四个课设. 当然这并不能作为好久没写博客的借口, 没写博客的主要原因只有一个: 懒. 最近又开始回顾C++的语法与特性(据说C++就是一门需要反复回顾的语言),以及学习C+ ...

  3. 【读书笔记】C++ primer 5th 从入门到自闭(一)

    这几天看了C++ primer 5th的一二章,有很多收获,但是有的地方因为翻译的问题也搞得理解起来颇为难受啊啊啊啊.尤其是const限定符,在C语言并没有这么多复杂的语法,在C++里面语法细节就多的 ...

  4. C++ Primer 5th 第1章 开始

    *****代码在Ubuntu g++ 5.31 / clang++ 3.8(C++11)下编写调试***** 每个C++程序必须有一个main( )函数,main( )函数的返回值也必须是int类型, ...

  5. c++ primer 5th 练习3.43

    #include <iostream> using namespace std; int main() { ][]={,,,,,,,,,,,}; /* for(int (&i)[4 ...

  6. C++ Primer 5th 第16章 模板与泛型编程

    模板是C++中泛型编程的基础,一个模板就是创建一个类或者函数的蓝图或者说公式. C++模板分为函数模板和类模板. 类模板则可以是整个类是个模板,类的某个成员函数是个模板,以及类本身和成员函数分别是不同 ...

  7. C++ Primer 5th 第15章 面向对象程序设计

    面向对象程序设计的核心思想是:数据抽象.继承和动态绑定. 数据抽象:将类的接口与实现分离: 继承:定义相似类型并对相似关系建模: 动态绑定:一定程度上上忽略相似类型间的区别,用同一方式使用它们. 1. ...

  8. C++ Primer 5th 第13章 拷贝控制

    当一个对象的引用或者指针离开作用域时,析构函数不会执行. 构造函数有初始化部分(初始化列表)和函数体. 析构函数有析构部分和函数,但析构函数的析构部分是隐式的.

  9. C++ Primer 5th 第12章 动态内存

    练习12.1:在此代码的结尾,b1 和 b2 各包含多少个元素? StrBlob b1; { StrBlob b2 = {"a", "an", "th ...

随机推荐

  1. Linux下基于Xampp的TestLink的安装部署

    由于项目需要,故需要搭建Testlink,且出于稳定,考虑在linux环境部署,当然windows系统也是可以的. 系统:64位操作系统 linux:centos6.8 testlink:1.9.14 ...

  2. ICEM-圆柱与长方体相切

    原视频下载地址:https://yunpan.cn/cqvgLe39ZU4Ke  访问密码 c1c9

  3. 从结构到性能,一文概述XGBoost、Light GBM和CatBoost的同与不同

    尽管近年来神经网络复兴并大为流行,但是 boosting 算法在训练样本量有限.所需训练时间较短.缺乏调参知识等场景依然有其不可或缺的优势.本文从算法结构差异.每个算法的分类变量时的处理.算法在数据集 ...

  4. Mysql -- BLOB, TEXT, GEOMETRY or JSON column 'result' can't have a default value

    执行上面的代码, 即可解决, 不过mysql重启之后还会有问题. 根本解决: 将mysql的配置文件中的sql_mode项 注释掉.

  5. css 文本省略号设置

    本文推荐2种方法. 1. css tip:只兼容chrome内核的浏览器.ff不支持. .box { overflow: hidden; /* 溢出时不显示溢出的内容 */ text-overflow ...

  6. vsCode中如何根据屏幕宽度自动换行

      在设置中搜索editor.wordWrap   文章来源:外星人来地球 欢迎关注,有问题一起学习欢迎留言.评论

  7. grub下如何指定哪个分区为根文件系统?

    答: 使用root命令,如: grub> set root=(hd0,msdos1)

  8. java@ 注解原理与使用

    Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对 ...

  9. 123457123456#0#-----com.yuming.baoBaoAiXueXi01hanzi--前拼后广--幼儿园宝宝学汉字

    123457123457#0#-----com.yuming.baoBaoAiXueXi01hanzi--前拼后广--幼儿园宝宝学汉字

  10. springboot下jar包方式运行Caused by: java.lang.ExceptionInInitializerError: null

    idea调试过程中不会出现此问题,异常如下 org.springframework.beans.factory.BeanCreationException: Error creating bean w ...