必威-必威-欢迎您

必威,必威官网企业自成立以来,以策略先行,经营致胜,管理为本的商,业推广理念,一步一个脚印发展成为同类企业中经营范围最广,在行业内颇具影响力的企业。

 每个泛型算法的实现都独立于单独的容器, 每

2019-09-21 22:30 来源:未知

C++

何以高效的行使STL:

第9章 顺序容器

第9章 顺序容器

C++primer第楚辞习题解答

演练9.1:对于下面的前后相继职务,vector、deque和list哪类容器最为符合?解释你的挑三拣四的理由。若无哪类容器优于其余容器,也请解释理由。

(a)读取固定数量的单词,将他们按字典顺序插入到容器中。我们就要下一章看到关联容器更符合那些主题材料。

(b)读取未明确的数量的单词,总是将新单词插入到终极。删除操作在头顶举办。

(c)从二个文本读取未确定的数量的莫西干发型。将这个数排序,然后将它们打字与印刷到正规输出。

(a) “按字典顺序插入到容器中”意味着进行插入排序操作,进而供给在容器内部频仍实行扦插操作,vector在尾巴部分之外的地方差怎么着删除成分异常慢,deque在头尾之外的岗位插入和删除成分不快,而list在别的职责插入、删除速度都异常的快。因而那几个任务选拔list更为适合。

(b)由于必要在头、尾分别举办扦插、删除等操作,因而将vector排除在外,deque和list都得以直达很好的性质。假若还亟需频仍进行任意拜候,则deque越来越好。

(c)由于整数占用空间异常的小,且异常快的排序算法需频繁随便拜望成分,将list排除在外。由于无需在头顶举行扦插、删除操作,因而采纳vector就能够,没有须求使用deque。

勤学苦练9.2:定义贰个list对象,其成分类型是int的deque。

list> lines;

演练9.3:构成迭代器范围的迭代器有什么限制?

几个迭代器begin和end必须指向同一个容器中的成分,只怕是容器最终叁个因素之后的岗位;並且,对begin再三开展递增操作,能够确认保证达到end,即end不在begin此前。

练习9.4:编写函数,接受部分对准vector的迭代器和二个int值。在五个迭代器钦命的限制中搜索给定的值,重临多少个布尔值来提议是或不是找到。

#include 
#include 
using std::cout;
using std::endl;
using std::vector;

bool find_x(vector::iterator begin, vector::iterator end, int x)
{
 for(; begin != end; ++begin)
  if (*begin == x)
   return true;
 return false;
}

int main()
{
 vector vec={1, 2, 4, 3, 5, 8, 10, 3, 4};
 cout<

练习9.5:重写上一题的函数,返回一个迭代器指向找到的元素。注意,程序必须处理未找到给定值的情况。  #include 
#include 
using std::cout;
using std::endl;
using std::vector;

vector::iterator find_x(vector::iterator begin, vector::iterator end, int x)
{
 for(; begin != end; ++begin)
  if (*begin == x)
   return begin;
 return end;
}

int main()
{
 vector vec={1, 2, 4, 3, 5, 8, 10, 3, 4};
 cout<

练习9.6:下面程序有何错误?你应该如何修改它?  list lst1;
list::iterator iter1 = lst1.begin(), iter2 = lst1.end();
while(iter1 < iter2) /*. . .*/

list不襄助<运算,只帮忙递增递减、==以及!=操作。可改成iter1 != iter2.

 

 

演练9.7:为了索引int的vector中的元素,应该运用什么项目?

应用迭代器类型vector::iterator来索引int的vector中的成分。

 

演练9.8:为了读取string的list中的成分,应该利用什么品种?假设写入list又该用哪些项目?

为了读取string的list中的成分,应使用list::valus_type,写入数据要求引用类型,使用list::reference。

 

练习9.9:begin和cbegin多少个函数有怎样分裂?

cbegin是C++新专门的学业引入来的,用来与auto结合使用。它回到指向容器第叁个要素的const迭代器,能够用来只读地探望容器,但不可能对容器元素实行修改。由此,当无需写访谈时,应该利用cbegin。

begin则是被重载过的,有五个版本:在那之中八个是const成员函数,也回到const迭代器;另三个则赶回普通迭代器,可以对容器成分进行修改。

 

勤学苦练9.10:下边4个指标分别是何等类型?

 

vector v1;
const vector v2;
auto it1 = v1.begin(), it2 = v2.begin();
auto it3 = v1.begin(), it4 = v2.cbegin();

v1是int的vector类型,能够修改v1的内容,包蕴丰硕、删除成分以及修改成分等操作。

 

v2是int的常量vector类型,其内容无法修改,增多、删除成分以及修改成分值等均不容许。

it1是一般迭代器,可对容器成分举办读写访谈,it2是const迭代器,无法对容器元素实行写访问。it3和it4都以const迭代器。  

 

演练9.11:对6种开立和开端化vector对象的措施,每一项都交由三个实例。解释各种vector包括如何值。

vector ilist; 暗许开始化,vector为空,容器中绝非有成分。

vector ilist2(ilist); ilist2起始化为ilist的正片,ilist必需与ilist2类型一样。

vector ilist = {1,2,3.0,4,5,6,7};初阶化为列表凉月素的正片,列表中的成分类型必需与ilist的因素类型相容,这里不可不是与整型相容的数值类型。

vector ilist3(ilist.begin()+2, ilist.end()-1);ilist3最早化为三个迭代器钦点范围中的成分的正片,范围中的成分类型必得与ilist的成分类型相容,这里ilist3被开端化为{3, 4, 5, 6}.

vector ilist4(7); 私下认可值初阶化,ilist4中校满含7个成分,每一种成分实行缺省的值开始化,对于int,也便是被赋值为0.

vector ilist5(7, 3); 钦点值初步化,ilist5被最初化为含有7个值为3的int。

 

练习9.12:对于收受二个器皿创立其拷贝的构造函数,和接受五个迭代器创立拷贝的构造函数,解释它们的不等。

经受多少个已有容器的组织函数会拷贝瓷容器中的全部因素,这样,起始化实现后,大家获取此容器的七个一模一样的正片、当我们确实须求八个容器的一体化拷贝时,这种开首化格局充裕有助于。那需要七个容器的花色以及其成分leixi9ng必须同盟。

当我们无需已有容器中的全体成分,而只是想拷贝当中某些因素时,可应用接受七个迭代器的构造函数。那毫不求容器类型一样,新容器和原容器中的成分类型也足以不一致,只要能将在拷贝的因素调换来要初步化的器皿的要素类型就可以。

 

勤学苦练9.13:怎样从一个list伊始化多个vector? 从多少个vector又该如何创建?编写代码验证你的答案。

对于那多少个开始化,能够行使限量开始化的方法来组织vector。

 

#include 
using std::cin;
using std::cout;
using std::endl;
using std::ends;
#include 
using std::vector;
#include 
using std::list;

int main()
{
 list li={0,1,2,3,4,5,5,6,7,9};
 list::iterator b=li.begin(), e=li.end();
 vector ivec1={1,2,3,2,5,7,0,2,5};

 for(;b!=e;++b)
  cout<<*b< ivec2(li.begin(), li.end());
 for(auto i:ivec2)
  cout<< ivec3(ivec1.begin(), ivec1.end());
 for(vector::iterator it=ivec3.begin();it!=ivec3.end();++it)
  cout<<*it<练习9.14:编写程序,讲一个list中的char *指针元素赋值给一个vector中的string。  #include 
#include 
#include 
#include 
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::list;

int main()
{
 list slist;
 char s1[] = "Hello";
 char s2[] = "C++";
 char s3[] = "Primer!";
 slist.push_back(s1);
 slist.push_back(s2);
 slist.push_back(s3);
 vector svec;
 svec.assign(slist.begin(), slist.end());
 cout<<

练习9.21:如果我们将第308页中使用的insert返回值将元素添加到list中的循环程序改写为将元素插入到vector中,分析循环将如何工作。 在循环之前,vector为空,此时将iter初始化为vector首位置,与初始化为尾位置效果是一样的。循环中第一次调用insert会将读取的第一个string插入到iter指向位置之前的位置,即令新元素成为vector的首元素。而insert的返回指向此元素的迭代器,我们将它赋予iter,从而使得iter始终指向vector的首元素。接下来每步亦是如此,将新string插入到vector首元素之前的位置,成为新的首元素,并使iter始终指向vector首。 练习9.22:假定iv是一个int的vector,下面的程序存在什么错误?你将如何修改? vector::iterator iter = iv.begin(), mid = iv.begin + iv.size()/2;
while(iter != mid)
 if(*iter == some_val)
  iv.insert(iter, 2*some_val);

循环中未对iter实行递增操作,iter无法向中部推动。其次,就算步入了++iter语句,由于向iv插入成分后,iter已经失效,++iter也不可能起到将迭代器向前推动三个成分的功能。

 

 

#include 
#include 
using std::cout;
using std::endl;
using std::vector;

int main()
{
 vector iv= {1, 1, 1, 1, 1};
 int some_val = 1;
 vector::iterator iter = iv.begin();
 int org_size = iv.size(), i = 0;

 while(i <= org_size/2) {
  if(*iter == some_val) {
   iter = iv.insert(iter, 2*some_val);
   ++iter;
   ++iter;
  }
  ++i;
 }

 for(iter = iv.begin(); iter != iv.end(); ++iter)
  cout<<*iter<

练习9.23:在本节第一个程序中,若c.size()为1,则val、val2、val3和val4的值会是什么?4个变量的值一样,指向唯一的一个元素。练习9.24:编写程序,分别使用at、下标运算符、front和begin提去一个vector中的第一个元素。在一个空vector上测试你的程序。#include 
using std::cout;
using std::endl;
#include 
using std::vector;

int main()
{
 vector vec;
 cout<<

练习9.25:对于第312页中删除一个范围内的元素的程序,如果elem1与elem2相等会发生什么?如果elem2是尾后迭代器,或者elem1和elem2皆为尾后迭代器,又会发生什么?如果两个迭代器elem1和elem2相等,则什么也不会发生,容器保持不变。哪怕两个迭代器是指向尾后位置也是如此,程序不会出错。因此elem1和elem2都是尾后迭代器时,容器保持不变。如果elem2为尾后迭代器,eleme1指向之前的合法位置,则会删除从elem1开始直至容器末尾的所有元素。练习9.26:使用下面代码定义的ia,将ia拷贝到一个vector和一个list中。使用单迭代器版本的erase从list中删除奇数元素,从vector中删除偶数元素。int ia[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 89}#include 
using std::endl;
using std::cout;
#include 
using std::vector;
using std::begin;
using std::end;
#include 
using std::list;

int main()
{
 int ia[]={0,1,1,2,3,5,8,13,21,55,89};
 vector vec(begin(ia), end(ia));
 list lis(begin(ia), end(ia));
 auto it=vec.begin();
 while(it!=vec.end())
 {
  if(!(*it%2))
   it=vec.erase(it);
  else
   ++it;
 }
 auto ir=lis.begin();
 while(ir!=lis.end())
 {
  if(*ir%2)
   ir=lis.erase(ir);
  else
   ++ir;
 }
 for(auto i: vec)
  cout<<

练习9.27:编写程序,查找并删除forward_list中的奇元素。#include 
using std::cout;
using std::endl;
#include 
using std::forward_list;

int main()
{
 forward_list flst={0,1,2,3,4,5,6,7,8,9};
 auto prev=flst.before_begin();
 auto curr=flst.begin();
 while(curr!=flst.end())
 {
  if(*curr & 1)
   curr=flst.erase_after(prev);
  else
  {
   prev=curr;
   ++curr;
  }
 }
 for(auto i: flst)
  cout<<>s1>>s2;
 find_insert(flst,s1,s2);
 cout<<"Now the forward_list is: "<

练习9.29:假定vec包含25个元素,那么vec.resize(100)会做什么?如果接下来调用vec.resize(10)会做什么?调用vec.resize(100)会向vec末尾添加75个元素,这些元素将进行值初始化。接下来调用vec.size(10)会将vec末尾90个元素删除。练习9.30:接受单个参数的resize版本对元素类型有什么限制?(如果有的话)对于元素时类类型,则单参数resize版本要求该类必须提供一个默认构造函数。练习9.31第316页中删除偶数值元素并复制奇数值元素的程序不能用于list或forward_list。为什么?修改程序,使之也能用于这些类型。list和forward_list与其他容器的一个不同是,迭代器不支持加减运算,因为链表中元素并非在内存中连续存储,无法通过地址的加减在元素间远距离移动,可以多次调用++来实现与迭代器加法相同的效果。#include 
using std::cout;
using std::endl;
#include 
using std::list;
#include 
using std::forward_list;

int main()
{
 list lt={0,1,2,3,4,5,6,7,8,9};
 forward_list flst={0,1,2,3,4,5,6,7,8,9};
 cout<<"List is :"<::iterator it=lt.begin();
 while(it!=lt.end())
 {
  if(*it%2)
  {
   it=lt.insert(it, *it);
   ++it;
   ++it;
  }
  else
  {
   it=lt.erase(it);
  }
 }
 cout<<"Now list is: "<

练习9.32:在第316页的程序中,向下面语句这样调用insert是否合法?如果不合法,为什么?iter = vi.insert(inter. *iter++);不合法。编译器在编译代码时,首先对*iter++求值,传递给insert第二个形参,此时iter已指向当前奇数的下一个元素,因此传递给insert的第一个参数是错误位置,程序执行会发生混乱。练习9.33:在本节最后一个例子中,如果不将insert的结果赋予begin,将会发生什么?编写程序,去掉此赋值语句,验证你的答案。向vector中插入新元素后,原有迭代器都会失效。因此,不将insert()返回的迭代器赋予begin,会使begin失效。继续使用begin会导致程序崩溃。 练习9.34:假定vi是一个保存int的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。iter = vi.begin();
while (iter !=  vi.end())
    if(*iter % 2)
        iter = vi.insert(iter, *iter);
++iter;

这段代码的第贰个谬误是忘记行使花括号,使得++iter编制程序循环后的首先条语句,而非循环所期望的循环体的末梢一条语句。除非容器为空,不然陷入死循环。若容器的第一个因素为偶数,布尔表达式为假,if语句真分支不会被施行,iter保持不改变。循环继续推行,真分支还是不会推行,iter继续保险不变,如此陷入死循环。若容器中的第一个因素是奇数,insert语句被调用,将该值插入到首成分之前,并将再次来到的迭代器赋予iter,由此iter指向新首成分,继续执行循环,会再三再四将首成分复制到容器首岗位,并令iter指向它,如此陷入死循环。
测验程序:

#include 
#include 
#include 
using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main()
{
 vector vi={1, 2, 3, 4, 5, 6, 7, 8, 9};
 auto iter = vi.begin();
 string tmp;
 while(iter != vi.end()) {
  if (*iter % 2)
   iter = vi.insert(iter, *iter);
  for(auto begin = vi.begin(); begin !=vi.end(); ++begin)
   cout<<*begin<<" ";
  cout<>tmp;
 }
 ++iter;

 return 0;
}

准确的做法是将++iter移入循环体,再加三个++iter就可以。

 

练习9.35:解释四个vector的capacity和size有啥分裂?

capacity重返已经为vector分配了多大内存空间,而size则赶回容器当前已经保存了有个别个因素。

 

演练9.36:多个器皿的capacity或者低于它的size吗?

不恐怕低于size。

 

勤学苦练9.37:为何list和array未有capacity成员函数?

list是链表,当有新因素插入时,会从内存空间分配多个新节点保存它;当从链表中去除成分时,该节点占用的内部存款和储蓄器空间会被当即释放。由此一个链表占用的内部存款和储蓄器空间总是与最近保存的因素所需的空中极度。而array是定点大小数组,内部存储器一次性分配,大小不改变,不会调换,由此它们均不须要capacity。

 

勤学苦练9.39:解释上面包车型地铁主次片段做了如何:

 

vector svec;
svec.reserve(1024);
string word;
while (cin >> word)
    svec.push_back(word);
svec.resize(svec.resize() + svec.size()/2);

首先,reserve为svec分配了10二十多少个要素的空中。随后,循环不断读入字符,增加到svec末尾,直到遇见文件停止符。那个进程中,假使读入的字符串数量十分的少于1024,则svec的capacity保持不改变,不会分配新的内部存款和储蓄器空间。不然,会按自然准则分配更加大的内部存款和储蓄器空间,并展开字符串的运动。接下来,resize将向svec末尾增多当前字符串数量50%那么多的新字符串,他们的值都是一无所得。若空间缺乏,会分配丰裕容纳那个字符串的内部存款和储蓄器空间。

勤学苦练9.40:假若上一题中的程序读入的2伍十八个词,在resize今后的器皿的capacity可能是稍微?假设读入了511个、1000个或1047个词吗?

若读入了2六二十一个词,则resize之后容器的capacity活死人384;若读入了511个词,则resize之后的容器capacity活死人768。若读入了1000个词,则resize之后容器的capacity是2048;若读了10肆15个词,照旧2048。

 

勤学苦练9.41:编写程序,从三个vector伊始化贰个string。

 

#include 
using std::vector;
#include 
using std::cout;
using std::endl;
#include 
using std::string;

int main()
{
 vector cvec={'b','e','a','u','t','i','f','u','l'};
 string s(cvec.data(),cvec.size());
 cout<<

练习9.42:假定你希望每次读取一个字符存入一个string中,而且知道最少需要读取100个字符,你应该如何提高程序的性能? 可以用reserve先为string分配100个字符的空间,然后逐个读取字符,用push_back添加到string末尾。 #include 
#include 
#include 
using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;

void inputString(string &s)
{
 s.reserve(100);
 char c;
 while(cin>>c)
  s.push_back(c);
}

int main()
{
 string s;
 inputString(s);
 cout<<

练习9.43:编写一个函数,接受三个string参数s、oldVal和newVal。使用迭代器及insert和erase函数将s中所有oldVal替换为newVal。测试你的程序,用它替换普通的简写形式,如,将”tho“替换为”though“,将”thru“替换为”through“。#include 
#include 
#include 
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::vector;
using std::string;

void rePlace(string &s, const string &oldVal, const string &newVal)
{
 auto l = oldVal.size();
 if (!l)
  return;
 auto iter = s.begin();
 while (iter <= s.end()-1) {
  auto iter1 = iter;
  auto iter2 = oldVal.begin();
  while(iter != oldVal.end() && *iter1 == *iter2) {
   ++iter1;
   ++iter2;
  }
  if(iter2 == oldVal.end()) {
   iter = s.erase(iter, iter1);
   if (newVal.size()) {
    iter2 = newVal.end();
    do {
     --iter2;
     iter = s.insert(iter, *iter2);
    } while(iter2 > newVal.begin());
   }
   iter += newVal.size();
  }
  else ++iter;
 }
}

int main()
{
 string s = "tho thru tho!";
 rePlace(s, "thru", "through");
 cout<<

练习9.44:重写上一题的函数,这次使用一个下标和replace。#include 
#include 
#include 
using std::cout;
using std::endl;
using std::vector;
using std::string;

void rePlace(string &s, const string &oldVal, const string &newVal)
{
 int p = 0;
 while((p=s.find(oldVal, p)) !=string::npos) {
  s.replace(p, oldVal.size(), newVal);
  p += newVal.size();
 }
}

int main()
{
 string s = "tho thru tho!";
 rePlace(s, "thru", "through");
 cout<<

练习9.45:编写一个函数,接受一个表示名字的string参数和两个分别表示前缀(如”Mr.“或”Ms.“)和后缀(如”Jr.“或”III“)的字符串。使用迭代器及insert和append函数将前缀和后缀添加到给定的名字中,将新生成的string返回。#include 
using std::cout;
using std::endl;
#include 
using std::string;

string combine(string &str,const string &s1, const string &s2)
{
 str.insert(0,s1);
 str.append(s2);
 return str;
}

int main()
{
 string str="Tom",s1="Mr.",s2="Jr.";
 combine(str,s1,s2);
 cout<<

练习9.46:重写上一题的函数,这次使用位置和长度来管理string,并只使用insert。#include 
using std::cout;
using std::endl;
#include 
using std::string;
#include 
using std::vector;

void name_string(string &name, const string &prefix, const string &suffix)
{
 name.insert(0, " ");
 name.insert(0, prefix);
 name.insert(name.size(), " ");
 name.insert(name.size(), suffix);
}

int main()
{
 string s = "James Bond";
 name_string (s, "Mr.", "II");
 cout<<

练习9.47:编写程序,首先查找string ”ab2c3d7R4E6“中每个数字字符,然后查找其中每个字母字符。编写两个版本的程序,第一个要使用find_first_of,第二个要使用find_first_of。#include 
using std::cout;
using std::endl;
#include 
using std::string;

void use_find_first_of(string str, string find_str)
{
    auto pos = 0;
    while((pos = str.find_first_of(find_str,pos)) != string::npos)
    {
        cout << "char: " << str[pos] << " index: " << pos << endl;
        ++pos; 
    }
    cout << endl;
}

void use_find_first_not_of(string str , string not_find_str)
{
    auto pos = 0;
    while((pos = str.find_first_not_of(not_find_str,pos)) != string::npos)
    {
        cout << "position: " << pos << " char: " << str[pos] << endl;
        ++pos;
    }
    cout << endl;
}

int main()
{
    string str = "abc3d7R4E6";
    string numbers = "0123456789";
    string letters = "abcdRE";

    use_find_first_of(str, numbers);
    use_find_first_of(str, letters);

    use_find_first_not_of(str, letters);
    use_find_first_not_of(str, numbers);
    return 0;
} 

勤学苦练9.48:假定name和numbers的定义如325页所示,numbers.find(name)重返什么?

s.find(args)查找s中args第壹遍面世的地方。因而,对325页给定的name和numbers,在numbers中海市蜃楼与name相称的字符串,find会重回npos。

练习9.49:假若一个字母延伸到中线之上,如d或f,则称其有上出底部分。固然贰个字母延伸到中线之下,如p或g,则称其有下出尾部分。编写程序,读入二个单词文件,输出最长的既不带有上出尾部分,也不不带有下出尾部分的单词。

 

#include 
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#include 
using std::string;
#include 
using std::ifstream;

void find_longest_word(ifstream &in)
{
 string s, longest_word;
 int max_length = 0;

 while (in >> s) {
  if(s.find_first_of("bdfghjklpqty") != string::npos)
   continue;
  cout<<<

<

<

<

<

<

<

<

<

<

<

<

练习9.1:对于上边的主次任务,vector、deque和list哪一种容器最为符合?解释你的挑三拣四的理由。若无哪类容器优于...

C++两种容器:list、vector和deque的不一致:

部分摘取:大CC《高效的应用STL》

  1. 梯次容器和涉及容器
    次第容器内的要素按其职分存款和储蓄和做客。
    涉及容器,其成分按钮(key)排序。

  2. 依次容器(sequential container)。
    各种容器的因素排列次序与成分值非亲非故,而是由成分增多到容器里的主次决定。 

  3. 标准库定义了三种顺序容器类型:vector、list 和 deque(是双端队列“double-ended queue”的简写,发音为“deck”)。
    头文件如下:
    #include <vector>
    #include <list>
    #include <deque> 

  4. 标准库还提供了三种容器适配器(adaptors)。适配器是基于原有的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。
    逐个容器适配器包含 stack、queue 和 priority_queue 类型。

  5. 依次容器

    vector 支持快速随机访问,支持下标访问 ,但在中间随机插入/删除速度慢
    list   支持快速插入/删除,不支持随机访问。
    deque   双端队列

     

    次第容器适配器

    stack
    后进先出(LIFO)堆栈
    queue 
    先进先出(FIFO)队列
    priority_queue 
    有优先级管理的队列 
  6. 不无的容器都以类模板:
    vector<string>    svec;       // empty vector that can hold strings
    list<int>         ilist;      // empty list that can hold ints
    deque<Sales_item> items;      // empty deque that holds Sales_items 

  7. 容器元素的起始化(构造函数)
    容器类型最常用的构造函数是暗许构造函数。在大多的前后相继中,使用默许构造函数能实现最好运营时品质,並且使容器更易于采用。

    C<T> c; 创建一个名为 c 的空容器。C 是容器类型名,如 vector,T 是元素类型,如 int 或 string 适用于所有容器
    C c(c2);  创建容器 c2 的副本 c;c 和 c2 必须具有相同的容器类型,并存放相同类型的元素。适用于所有容器。要求容器类型和容器里元素的类型都必须相同。
    C c(b, e); 创建 c,其元素是迭代器 b 和 e 标示的范围内元素的副本。适用于所有容器。不要求容器类型相同,容器里元素类型也可以不相同,相互兼容即可。
    C c(n, t);      用 n 个值为 t 的元素创建容器 c,其中值 t 必须是容器类型 C 的元素类型的值,或者是可转换为该类型的值。 只适用于顺序容器。
    C c(n); 创建有 n 个值初始化(第 3.3.1 节)(value-initialized)元素的容器 c。 只适用于顺序容器。

     

  8. 将一个容器初阶化为另贰个容器的别本。 
    vector<int> ivec;
    vector<int> ivec2(ivec);   // ok: ivec is vector<int> 
    将三个器皿复制给另七个器皿时,容器类型要素类型都不可能区别。 

  9. 开始化为一段元素的别本。
    无法一贯将一种容器内的成分复制给另一种容器,但允许通过传递一对迭代器直接达成该兑现该意义。
    行使迭代器时,不供给容器类型同样,容器内的因素类型也得以不均等,只要它们相互相配,能够即将复制的成分调换为所营造的新容器的因素类型,就可以兑现复制。 
    list<string> slist(svec.begin(), svec.end());

    指南针正是迭代器,由此同意通过行使内置数组中的一对指针初叶化容器。
    char *words[] = {"stately", "plump", "buck", "mulligan"};
    size_t words_size = sizeof(words)/sizeof(char *);
    list<string> words2(words, words + words_size); 

  10. 分红和初阶化钦命数量的成分
    开创顺序容器时,可显式内定容器大小和一个(可选的)成分最初化式。容器大小可以是常量或极度量表达式,成分起初化则必得是可用于开首化其成分类型的对象的值:
    const list<int>::size_type list_size = 64;
    list<string> slist(list_size, "eh?"); // 64 strings, each is eh?
    这段代码表示 slist 含有 61个要素,每种成分都被最早化为“eh?”字符串。
    也得以只钦命容器大小: 
    list<int> ilist(64); // 64 elements, each initialized to 0 

  11. 容器内成分的门类约束
    容器元素类型必需满意以下八个约束:
    **•  元素类型必得扶助赋值运算。
    •  成分类型的靶子必需可以复制。
    涉嫌容器的键还必需扶助“<”操作符。

    **

  12. 容器的器皿
    可定义成分是容器类型的器皿:vector< vector<string> > lines; //必得用空格隔开分离五个相邻的 > 符号。

  13. 常用迭代器的运算

    *iter                                返回迭代器 iter 所指向的元素的引用 
    iter->mem 对 iter 进行解引用,获取指定元素中名为 mem 的成员。等效于(*iter).mem 
    ++iter,iter++ 给 iter 加 1,使其指向容器里的下一个元素 
    --iter,iter-- 给 iter 减 1,使其指向容器里的前一个元素
    iter1 == iter2,
    iter1 != iter2
    比较两个迭代器是否相等(或不等)。当两个迭代器指向同一个容器中的同一个元素,或者当它们都指向同一个容器的超出末端的下一位置时,两个迭代器相等 

     

  14.  vector 和 deque 容器的迭代器只有支持:迭代器算术运算:iter + n , iter - n , iter1 += iter2, iter1 -= iter2,  
    除了 == 和 != 之外的涉及操作符来: > , >=, < , <=

  15. list迭代器不帮忙算术运算,也不支持关系元算,只援助:++iter, iter++ 和 iter1 == iter2, iter1 != iter2 。

  16. 迭代器范围:左闭合区间
    [ first, last) : 表示范围从 first 初始,到 last 甘休,但不包括last。
    1).  当 first 与 last 相等时,迭代器范围为空;
    2).  当 first 与不等于时,迭代器范围内至少有一个因素,而且 first 指向该区间中的第一要素。别的,通过若干次自增运算能够使 first 的值持续增大,直到 first == last 截至。 

  17. 容器定义的品种

    size_type 无符号整型,足以存储此容器类型的最大可能容器长度 
    iterator   此容器类型的迭代器类型
    const_iterator   元素的只读迭代器类型
    reverse_iterator   按逆序寻址元素的迭代器 
    const_reverse_iterator   元素的只读(不能写)逆序迭代器
    difference_type 足够存储两个迭代器差值的有符号整型,可为负数 
    value_type 元素类型 
    reference 元素的左值类型,是 value_type& 的同义词 
    const_reference 元素的常量左值类型,等效于 const value_type&

     

  18. 全体容器的迭代器帮衬的操作: begin  和  end  成员 
    c.begin() : 重临三个迭代器,它指向容器 c 的第一个因素
    c.end() : 再次来到三个迭代器,它指向容器 c 的末尾多少个成分的下一职位 
    c.rbegin() : 重回一个逆序迭代器,它指向容器 c 的末段叁个要素 
    c.rend() : 重回贰个逆序迭代器,它指向容器 c 的第贰个因素前边的任务

  19. 容器成分都是副本
    在容器中添日币素时,系统是将成分值复制到容器里(所以须求成分的类型必得协理复制)。类似地,使用一段成分先导化新容器时,新容器存放的是原始成分的别本。被复制的原始值与新容器中的元素各不相干,此后,容器内成分值爆发变化时,被复制的原值不会受到震慑,反之亦然。 

  20. **借使用容器存别本,则容器销毁的时候,别本也会活动被剔除。
    倘若用容器存指针,则容器销毁的时候,不会去除这一个指针所针对的对象,因此必得先手工业删除完结之后,再销毁容器。

    **

  21. 逐个容器中添日币素

    c.push_back(t)  在容器 c 的尾部添加值为 t 的元素。返回 void 类型。 
    c.push_front(t)  在容器 c 的前端添加值为 t 的元素。返回 void 类型。只适用于 list 和 deque 容器类型。
    c.insert(p,t)  在迭代器 p 所指向的元素前面插入值为 t 的新元素。返回指向新添加元素的迭代器。
    c.insert(p,n,t) 在迭代器 p 所指向的元素前面插入 n 个值为 t 的新元素。返回 void 类型 。
    c.insert(p,b,e) 在迭代器 p 所指向的元素前面插入由迭代器 b 和 e 标记的范围内的元素。返回 void 类型。
  22. 添美成分恐怕会使迭代器失效
    其余 insert 或 push 操作都可能引致一些或有所迭代器失效。当编辑循环将成分插入到 vector 或 deque 容器中时,程序必得保障迭代器在历次循环后都获得更新。 

  23. 关系操作符
    全体的容器类型都帮衬用关系操作符来促成四个容器的可比。绝相比的容器必须持有同样的器皿类型,何况其成分类型也必得一致。

  24. 次第容器的轻重操作

    c.size()  返回容器 c 中的元素个数。返回类型为 c::size_type 
    c.max_size() 返回容器 c 可容纳的最多元素个数,返回类型为c::size_type
    c.empty()  返回标记容器大小是否为 0 的布尔值 
    c.resize(n) 调整容器 c 的长度大小,使其能容纳 n 个元素,如果 n < c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素 
    c.resize(n,t) 调整容器 c 的长度大小,使其能容纳 n 个元素。所有新添加的元素值都为 t 

    resize 操作大概会使迭代器失效。在 vector 或 deque 容器上做 resize 操作有不小可能率会使其持有的迭代器都失效。

  25. 做客顺序容器内成分的操作 

    c.back() 返回容器 c 的最后一个元素的引用。如果 c 为空,则该操作未定义
    c.front() 返回容器 c 的第一个元素的引用。如果 c 为空,则该操作未定义
    c[n] 返回下标为 n 的元素的引用 如果 n <0 或 n >= c.size(),则该操作未定义。只适用于 vector 和 deque 容器
    c.at(n) 返回下标为 n 的元素的引用。如果下标越界,则该操作未定义。只适用于 vector 和 deque 容器

     使用越界的下标,或调用空容器的 front 或 back 函数,都会产生程序出现严重的不当。  

  26. 删去顺序容器内成分的操作 

    c.erase(p) 删除迭代器 p 所指向的元素返回一个迭代器,它指向被删除元素后面的元素。如果 p 指向容器内的最后一个元素,则返回的迭代器指向容器的超出末端的下一位置。如果 p 本身就是指向超出末端的下一位置的迭代器,则该函数未定义。
    c.erase(b,e) 删除迭代器 b 和 e 所标记的范围内所有的元素返回一个迭代器,它指向被删除元素段后面的元素。如果 e 本身就是指向超出末端的下一位置的迭代器,则返回的迭代器也指向容器的超出末端的下一位置。
    c.clear()  删除容器 c 内的所有元素。返回 void。
    c.pop_back() 删除容器 c 的最后一个元素。返回 void。如果 c 为空容器,则该函数未定义。
    c.pop_front() 删除容器 c 的第一个元素,返回 void。如果 c 为空容器,则该函数未定义。只适用于 list 或 deque 容器。
  27. 依次容器的赋值操作 

    c1 = c2 删除容器 c1 的所有元素,然后将 c2 的元素复制给 c1。c1 和c2 的类型(包括容器类型和元素类型)必须相同。
    c1.swap(c2) 交换内容:调用完该函数后,c1 中存放的是 c2 原来的元素,c2 中存放的则是 c1 原来的元素。c1 和 c2 的类型必须相同。该函数的执行速度通常要比将 c2 复制到 c1 的操作快。
    c.assign(b,e) 重新设置 c 的元素:将迭代器 b 和 e 标记的范围内所有的元素复制到 c 中。b 和 e 必须不是指向 c 中元素的迭代器 。
    c.assign(n,t)  将容器 c 重新设置为存储 n 个值为 t 的元素。
  28. 选拔容器的晋升
    1).  要是程序要求自由拜会成分,则应利用 vector 或 deque 容器。
    2).  若是程序必得在容器的中游地点插入或删除成分,则应利用 list 容器。 
    3).  假如程序不是在容器的中级地点,而是在容器首部或尾巴部分插入或删除成分,则应运用 deque 容器。
    4).  若是只需在读取输入时在容器的中等地点插入成分,然后需求自由访谈成分,则可思虑在输入时将成分读入到一个list 容器,接着对此容注重新排序,使其符合各样访谈,然后将排序后的 list 容器复制到三个 vector 容器。 

  29. string
    string类型能够视为字符容器。除了部分特殊操作,string 类型提供与 vector 容器相同的操作。string 类型与 vector 容器不相同的是,它不支持以栈格局垄断容器:在 string 类型中不可能应用 front、back 和 pop_back 操作。

    string 类型提供了容器类型不帮忙任何三种操作:
    •  substr 函数,重临当前 string 对象的子串。
    •  append 和 replace 函数,用于修改 string 对象。
    •  一层层 find 函数,用于查找 string 对象。 

  30. string:substr 操作
    行使 substr 操作可在钦点 string 对象中找出必要的子串。

    s.substr(pos, n) 返回一个 string 类型的字符串,它包含 s 中从下标 pos开始的 n 个字符
    s.substr(pos)  返回一个 string 类型的字符串,它包含从下标 pos 开始到s 末尾的所有字符 
    s.substr() 返回 s 的副本 

     

  31. append 和 replace

    s.append(args) 将 args 串接在 s 后面。返回 s 引用
    s.replace(pos, len, args)          删除 s 中从下标 pos 开始的 len 个字符,用 args 指定的字符替换之(在pos位置插入args)。返回 s 的引用 
    s.replace(b, e, args) 删除迭代器 b 和 e 标记范围内所有的字符,用 args 替换之(在pos位置插入args)。返回 s 的引用 

     

  32. string 类型的搜寻操作

    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 的字符

     

  1. 依次容器和涉嫌容器
    种种容器内的要素按其岗位存款和储蓄和做客。
    波及容器,其成分按钮(key)排序。

  2. 梯次容器(sequential container)。
    各样容器的因素排列次序与成分值非亲非故,而是由成分增多到容器里的主次决定。 

  3. 标准库定义了三种顺序容器类型:vector、list 和 deque(是双端队列“double-ended queue”的简写,发音为“deck”)。
    头文件如下:
    #include <vector>
    #include <list>
    #include <deque> 

  4. 规范库还提供了三种容器适配器(adaptors)。适配器是基于原有的器皿类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。
    逐条容器适配器包蕴 stack、queue 和 priority_queue 类型。

  5. 梯次容器

    vector 支持快速随机访问,支持下标访问 ,但在中间随机插入/删除速度慢
    list   支持快速插入/删除,不支持随机访问。
    deque   双端队列

     

    依次容器适配器

    stack
    后进先出(LIFO)堆栈
    queue 
    先进先出(FIFO)队列
    priority_queue 
    有优先级管理的队列 
  6. 享有的器皿都以类模板:
    vector<string>    svec;       // empty vector that can hold strings
    list<int>         ilist;      // empty list that can hold ints
    deque<Sales_item> items;      // empty deque that holds Sales_items 

  7. 容器成分的最初化(构造函数)
    容器类型最常用的构造函数是暗许构造函数。在许多的顺序中,使用私下认可构造函数能完成最好运维时品质,并且使容器更易于选择。

    C<T> c; 创建一个名为 c 的空容器。C 是容器类型名,如 vector,T 是元素类型,如 int 或 string 适用于所有容器
    C c(c2);  创建容器 c2 的副本 c;c 和 c2 必须具有相同的容器类型,并存放相同类型的元素。适用于所有容器。要求容器类型和容器里元素的类型都必须相同。
    C c(b, e); 创建 c,其元素是迭代器 b 和 e 标示的范围内元素的副本。适用于所有容器。不要求容器类型相同,容器里元素类型也可以不相同,相互兼容即可。
    C c(n, t);      用 n 个值为 t 的元素创建容器 c,其中值 t 必须是容器类型 C 的元素类型的值,或者是可转换为该类型的值。 只适用于顺序容器。
    C c(n); 创建有 n 个值初始化(第 3.3.1 节)(value-initialized)元素的容器 c。 只适用于顺序容器。

     

  8. 将贰个容器伊始化为另二个容器的别本。 
    vector<int> ivec;
    vector<int> ivec2(ivec);   // ok: ivec is vector<int> 
    将二个器皿复制给另一个器皿时,容器类型要素类型都不能够不相同。 

  9. 起首化为一段成分的别本。
    无法一贯将一种容器内的因素复制给另一种容器,但允许通过传递一对迭代器间接实现该兑现该意义。
    行使迭代器时,不要求容器类型一样,容器内的要素类型也得以不均等,只要它们相互合营,可以将在复制的因素转变为所营造的新容器的因素类型,就能够兑现复制。 
    list<string> slist(svec.begin(), svec.end());

    指南针便是迭代器,因而同意通过行使内置数组中的一对指针初阶化容器。
    char *words[] = {"stately", "plump", "buck", "mulligan"};
    size_t words_size = sizeof(words)/sizeof(char *);
    list<string> words2(words, words + words_size); 

  10. 分红和早先化钦点数量的成分
    始建顺序容器时,可显式钦点容器大小和贰个(可选的)成分发轫化式。容器大小能够是常量或特别量表明式,成分初叶化则必得是可用于伊始化其成分类型的对象的值:
    const list<int>::size_type list_size = 64;
    list<string> slist(list_size, "eh?"); // 64 strings, each is eh?
    这段代码表示 slist 含有 63个要素,各样成分都被初始化为“eh?”字符串。
    也得以只钦点容器大小: 
    list<int> ilist(64); // 64 elements, each initialized to 0 

  11. 容器内成分的品种约束
    容器成分类型务必满足以下四个约束:
    **•  元素类型必需协理赋值运算。
    •  成分类型的靶子必须能够复制。
    关系容器的键还必需协助“<”操作符。

    **

  12. 容器的容器
    可定义成分是容器类型的器皿:vector< vector<string> > lines; //必需用空格隔开分离四个相邻的 > 符号。

  13. 常用迭代器的运算

    *iter                                返回迭代器 iter 所指向的元素的引用 
    iter->mem 对 iter 进行解引用,获取指定元素中名为 mem 的成员。等效于(*iter).mem 
    ++iter,iter++ 给 iter 加 1,使其指向容器里的下一个元素 
    --iter,iter-- 给 iter 减 1,使其指向容器里的前一个元素
    iter1 == iter2,
    iter1 != iter2
    比较两个迭代器是否相等(或不等)。当两个迭代器指向同一个容器中的同一个元素,或者当它们都指向同一个容器的超出末端的下一位置时,两个迭代器相等 

     

  14.  vector 和 deque 容器的迭代器独有扶助:迭代器算术运算:iter + n , iter - n , iter1 += iter2, iter1 -= iter2,  
    除了 == 和 != 之外的涉嫌操作符来: > , >=, < , <=

  15. list迭代器不补助算术运算,也不补助关系元算,只援助:++iter, iter++ 和 iter1 == iter2, iter1 != iter2 。

  16. 迭代器范围:左闭合区间
    [ first, last) : 表示范围从 first 初叶,到 last 截至,但不包涵last。
    1).  当 first 与 last 相等时,迭代器范围为空;
    2).  当 first 与不等于时,迭代器范围内至少有一个要素,並且 first 指向该区间中的第一成分。其余,通过若干次自增运算能够使 first 的值持续增大,直到 first == last 截至。 

  17. 容器定义的门类

    size_type 无符号整型,足以存储此容器类型的最大可能容器长度 
    iterator   此容器类型的迭代器类型
    const_iterator   元素的只读迭代器类型
    reverse_iterator   按逆序寻址元素的迭代器 
    const_reverse_iterator   元素的只读(不能写)逆序迭代器
    difference_type 足够存储两个迭代器差值的有符号整型,可为负数 
    value_type 元素类型 
    reference 元素的左值类型,是 value_type& 的同义词 
    const_reference 元素的常量左值类型,等效于 const value_type&

     

  18. 抱有容器的迭代器补助的操作: begin  和  end  成员 
    c.begin() : 重回二个迭代器,它指向容器 c 的首先个因素
    c.end() : 重返三个迭代器,它指向容器 c 的末尾贰个成分的下一岗位 
    c.rbegin() : 再次来到三个逆序迭代器,它指向容器 c 的聊起底几个成分 
    c.rend() : 重返二个逆序迭代器,它指向容器 c 的首先个要素前边的职位

  19. 容器元素都以别本
    在容器中添美成分时,系统是将成分值复制到容器里(所以供给成分的种类必需帮忙复制)。类似地,使用一段成分伊始化新容器时,新容器寄放的是原始成分的别本。被复制的原始值与新容器中的成分各不相干,此后,容器内成分值爆发变化时,被复制的原值不相会前碰到震慑,反之亦然。 

  20. **若是用容器存别本,则容器销毁的时候,别本也会活动被去除。
    要是用容器存指针,则容器销毁的时候,不会删除那几个指针所指向的对象,因而必需先手工业删除完结之后,再销毁容器。

    **

  21. 依次容器中添英镑素

    c.push_back(t)  在容器 c 的尾部添加值为 t 的元素。返回 void 类型。 
    c.push_front(t)  在容器 c 的前端添加值为 t 的元素。返回 void 类型。只适用于 list 和 deque 容器类型。
    c.insert(p,t)  在迭代器 p 所指向的元素前面插入值为 t 的新元素。返回指向新添加元素的迭代器。
    c.insert(p,n,t) 在迭代器 p 所指向的元素前面插入 n 个值为 t 的新元素。返回 void 类型 。
    c.insert(p,b,e) 在迭代器 p 所指向的元素前面插入由迭代器 b 和 e 标记的范围内的元素。返回 void 类型。
  22. 添日币素可能会使迭代器失效
    任何 insert 或 push 操作都大概导致某个或享有迭代器失效。当编辑循环将元素插入到 vector 或 deque 容器中时,程序必得确定保证迭代器在历次循环后都赢得更新。 

  23. 关系操作符
    有着的容器类型都援助用关系操作符来促成五个容器的比较。相相比较的容器必得有所同等的器皿类型,而且其成分类型也必得一律。

  24. 各样容器的轻重操作

    c.size()  返回容器 c 中的元素个数。返回类型为 c::size_type 
    c.max_size() 返回容器 c 可容纳的最多元素个数,返回类型为c::size_type
    c.empty()  返回标记容器大小是否为 0 的布尔值 
    c.resize(n) 调整容器 c 的长度大小,使其能容纳 n 个元素,如果 n < c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素 
    c.resize(n,t) 调整容器 c 的长度大小,使其能容纳 n 个元素。所有新添加的元素值都为 t 

    resize 操作可能会使迭代器失效。在 vector 或 deque 容器上做 resize 操作有异常的大希望会使其持有的迭代器都失效。

  25. 拜候顺序容器内成分的操作 

    c.back() 返回容器 c 的最后一个元素的引用。如果 c 为空,则该操作未定义
    c.front() 返回容器 c 的第一个元素的引用。如果 c 为空,则该操作未定义
    c[n] 返回下标为 n 的元素的引用 如果 n <0 或 n >= c.size(),则该操作未定义。只适用于 vector 和 deque 容器
    c.at(n) 返回下标为 n 的元素的引用。如果下标越界,则该操作未定义。只适用于 vector 和 deque 容器

     使用越界的下标,或调用空容器的 front 或 back 函数,都会促成程序出现严重的错误。  

  26. 除去顺序容器内成分的操作 

    c.erase(p) 删除迭代器 p 所指向的元素返回一个迭代器,它指向被删除元素后面的元素。如果 p 指向容器内的最后一个元素,则返回的迭代器指向容器的超出末端的下一位置。如果 p 本身就是指向超出末端的下一位置的迭代器,则该函数未定义。
    c.erase(b,e) 删除迭代器 b 和 e 所标记的范围内所有的元素返回一个迭代器,它指向被删除元素段后面的元素。如果 e 本身就是指向超出末端的下一位置的迭代器,则返回的迭代器也指向容器的超出末端的下一位置。
    c.clear()  删除容器 c 内的所有元素。返回 void。
    c.pop_back() 删除容器 c 的最后一个元素。返回 void。如果 c 为空容器,则该函数未定义。
    c.pop_front() 删除容器 c 的第一个元素,返回 void。如果 c 为空容器,则该函数未定义。只适用于 list 或 deque 容器。
  27. 次第容器的赋值操作 

    c1 = c2 删除容器 c1 的所有元素,然后将 c2 的元素复制给 c1。c1 和c2 的类型(包括容器类型和元素类型)必须相同。
    c1.swap(c2) 交换内容:调用完该函数后,c1 中存放的是 c2 原来的元素,c2 中存放的则是 c1 原来的元素。c1 和 c2 的类型必须相同。该函数的执行速度通常要比将 c2 复制到 c1 的操作快。
    c.assign(b,e) 重新设置 c 的元素:将迭代器 b 和 e 标记的范围内所有的元素复制到 c 中。b 和 e 必须不是指向 c 中元素的迭代器 。
    c.assign(n,t)  将容器 c 重新设置为存储 n 个值为 t 的元素。
  28. 分选容器的提醒
    1).  纵然程序要求自由访谈成分,则应使用 vector 或 deque 容器。
    2).  假若程序必得在容器的中间地点插入或删除成分,则应使用 list 容器。 
    3).  假使程序不是在容器的中游地点,而是在容器首部或尾巴部分插入或删除成分,则应利用 deque 容器。
    4).  如若只需在读取输入时在容器的中间地方插入成分,然后须求自由拜见成分,则可思量在输入时将成分读入到三个list 容器,接着对此容重视新排序,使其符合各样访谈,然后将排序后的 list 容器复制到三个 vector 容器。 

  29. string
    string类型能够说是字符容器。除了有个别新鲜操作,string 类型提供与 vector 容器一样的操作。string 类型与 vector 容器差异的是,它不帮忙以栈方式垄断(monopoly)容器:在 string 类型中无法应用 front、back 和 pop_back 操作。

    string 类型提供了容器类型不支持任何三种操作:
    •  substr 函数,再次回到当前 string 对象的子串。
    •  append 和 replace 函数,用于修改 string 对象。
    •  一多元 find 函数,用于查找 string 对象。 

  30. string:substr 操作
    利用 substr 操作可在内定 string 对象中探索须要的子串。

    s.substr(pos, n) 返回一个 string 类型的字符串,它包含 s 中从下标 pos开始的 n 个字符
    s.substr(pos)  返回一个 string 类型的字符串,它包含从下标 pos 开始到s 末尾的所有字符 
    s.substr() 返回 s 的副本 

     

  31. append 和 replace

    s.append(args) 将 args 串接在 s 后面。返回 s 引用
    s.replace(pos, len, args)          删除 s 中从下标 pos 开始的 len 个字符,用 args 指定的字符替换之(在pos位置插入args)。返回 s 的引用 
    s.replace(b, e, args) 删除迭代器 b 和 e 标记范围内所有的字符,用 args 替换之(在pos位置插入args)。返回 s 的引用 

     

  32. string 类型的查找操作

    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 的字符

     

一、容器

一 当指标非常的大时,建立指针的器皿并非目的的器皿

第10章 关联容器

第10章 关联容器

小常识

1、queue、stack不可遍历,list迭代器不得以采用"it=it+1",而能够使用"it++"

2、我们为何这么写循环?

for(vector<int>::iterator iter = xx.begin(); iter != xx.end(); ++ iter){...}

假定是一个空的list,那样写会报错么?不会,因为空容器的begin与end的再次回到值是一致的,进不了循环。不过,需求注意的是,他们不是空指针

std::vector::begin()
Returns an iterator to the first element of the container.
If the container is empty, the returned iterator will be equal to end().

std::vector::end()
Returns an iterator to the element following the last element of the container.
This element acts as a placeholder; attempting to access it results in undefined behavior.

3、erase()的写法

可以参谋

for(vector<int>::iterator it=vecInt.being(); it!=vecInt.end{    //小括号里不需写 ++it   if{        it  =  vecInt.erase;              //以迭代器为参数,删除某元素及其迭代器并把数据删除后的下一个元素位置返回给迭代器。此时,不执行         //++it;         //这里it为实参,经转变为形参后,形参被删除,但是由于实参it是迭代器,是指针,所以实参it也成了野       //指针,所以需要重新赋值   }   else   {       ++it;   }}

那时候,如若容器为空,erase()也尚未未有标题。

1 STL基于拷贝的方法的来行事,任何索要归入STL中的成分,都会被复制

  1. 关联容器帮助通过来快捷地搜索和读取元素;顺序容器是经过成分在容器中的位置顺序存款和储蓄和访谈成分。

  2. map 的因素以键-值(key-value)对的方式协会:键用作成分在 map 中的索引,而值则象征所蕴藏和读取的多少。
    set 仅富含一个键,并实用地辅助有关有个别键是或不是留存的询问。
    set适用于积攒区别值的聚合。map 容器则更适用于必要仓库储存(以致修改)每一个键所关联的值的状态。

    map 关联数组,元素通过键来存储和读取
    set 大小可变的集合,支持通过键实现的快速读取
    multimap 支持同一个键多次出现的 map 类型
    multiset 支持同一个键多次出现的 set 类型 

     

  3. pair类型
    pair也是一种模板类型。 

    pair<T1, T2> p1;  创建一个空的 pair 对象,它的两个元素分别是 T1 和 T2 类型,采用值初始化。
    pair<T1, T2> p1(v1, v2); 创建一个 pair 对象,它的两个元素分别是 T1 和 T2 ,其中 first 成员初始化为 v1,而 second 成员初始化为 v2。 
    make_pair(v1,v2); 以 v1 和 v2 值创建一个新 pair 对象,其元素类型分别是v1 和 v2 的类型。
    p1 < p2  两个 pair 对象之间的小于运算,其定义遵循字典次序:如果 p1.first < p2.first 或者 !(p2.first < p1.first) && p1.second < p2.second,则返回 true 。
    p1 == p2   如果两个 pair 对象的 first 和 second 成员依次相等,则这两个对象相等。该运算使用其元素的 == 操作符。
    p.first  返回 p 中名为 first 的(公有)数据成员。
    p.second 返回 p 的名为 second 的(公有)数据成员 。

     

  4. 波及容器不提供front、push_front、pop_front、back、push_back以及pop_back操作;

  5. 要利用map对象,则必需含有map头文件;
    定义map对象时,必得各自指明键和值的品类。map<string, int> word_count;

    map<k, v> m;                     创建一个名为 m 的空 map 对象,其键和值的类型分别为 k 和 v
    map<k, v> m(m2);  创建 m2 的副本 m,m 与 m2 必须有相同的键类型和值类型 
    map<k, v> m(b, e);  创建 map 类型的对象 m,存储迭代器 b 和 e 标记的范围内所有元素的副本。元素的类型必须能转换为 pair<const k, v> 

     

  6. 涉嫌容器的键类型必得援助 < 操作符,并且该操作符应能“正确地劳作”;

  7. map 定义的连串

    map<K, V>::key_type                    在 map 容器中,用做索引的键的类型 
    map<K,V>::mapped_type 在 map 容器中,键所关联的值的类型 
    map<K,V>::value_type 一个 pair 类型,它的 first 元素具有 const map<K, V>::key_type 类型,而 second 元素则为 map<K, V>::mapped_type 类型 

    谨记: value_type 是 pair 类型,它的值成员可以修改,但键成员不能够修改。 

  8. 给 map 添日币素
    (1) 使用insert 成员贯彻;
    (2) 先用下标操作符获取成分,然后给拿走的成分赋值。

  9. 行使下标访谈 map 对象
    选择下标[i]做客map中官样文章的因素将促成在map容器中增多贰个新的要素,它的键即为该下标值;

  10. map::insert 的使用 

    m.insert(e) e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则插入一个值为 e.second 的新元素;如果该键在 m 中已存在,则保持 m 不变。该函数返回一个 pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素。
    m.insert(beg, end)                                                                        beg 和 end 是标记元素范围的迭代器,其中的元素必须为 m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在,则将该键及其关联的值插入到 m。返回 void 类型 。
    m.insert(iter,e)  e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则创建新元素,并以迭代器 iter 为起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具有给定键的元素。

     

  11. 寻找并读取 map 中的成分
    不修改 map 对象的查询操作:

    m.count(k)  返回 m 中 k 的出现次数
    m.find(k) 如果 m 容器中存在按 k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。

     

  12. 从map中删除成分

    m.erase(k)   删除 m 中键为 k 的元素。返回 size_type 类型的值,表示删除的元素个数 
    m.erase(p)  从 m 中删除迭代器 p 所指向的元素。p 必须指向 m 中确实存在的元素,而且不能等于 m.end()。返回 void 
    m.erase(b, e)                                                 从 m 中删除一段范围内的元素,该范围由迭代器对 b 和 e 标记。b 和 e 必须标记 m 中的一段有效范围:即 b 和 e 都必须指向 m 中的元素或最后一个元素的下一个位置。而且,b 和 e 要么相等(此时删除的范围为空),要么 b 所指向的元素必须出现在 e 所指向的元素之前。返回 void 类型 
  13. map 对象的迭代遍历
    与其余容器一样,map 同样提供 begin 和 end 运算,以浮动用于遍历整个容器的迭代器。比如,可正如将 map 容器 word_count 的内容输出:
    map<string, int>::const_iterator  map_it = word_count.begin();
    while (map_it != word_count.end())
     {
             cout << map_it->first << " occurs "  << map_it->second << " times" << endl;
             ++map_it;

    在动用迭代器遍历map 容器时,迭代器指向的因素按钮的升序排列。

  14. set

    map 容器是键-值对的成团,set 容器只是独自的键的集纳。
    三种分歧包括:set 不协助下标操作符,并且未有定义 mapped_type 类型。
    在 set 容器中,value_type 不是 pair 类型,而是与 key_type 一样的等级次序。它们指的都以 set 中存款和储蓄的因素类型。与 map 同样,set 容器存款和储蓄的键也必需独一,何况不可能修改。 

  1. 关系容器帮助通过来飞速地搜索和读取成分;顺序容器是透过成分在容器中的位置顺序存款和储蓄和会见成分。

  2. map 的要素以键-值(key-value)对的款式协会:键用作成分在 map 中的索引,而值则意味着所蕴藏和读取的数码。
    set 仅满含二个键,并有效地支撑有关有个别键是或不是留存的查询。
    set适用于储存不相同值的集纳。map 容器则更适用于要求仓库储存(以至修改)各类键所关联的值的意况。

    map 关联数组,元素通过键来存储和读取
    set 大小可变的集合,支持通过键实现的快速读取
    multimap 支持同一个键多次出现的 map 类型
    multiset 支持同一个键多次出现的 set 类型 

     

  3. pair类型
    pair也是一种模板类型。 

    pair<T1, T2> p1;  创建一个空的 pair 对象,它的两个元素分别是 T1 和 T2 类型,采用值初始化。
    pair<T1, T2> p1(v1, v2); 创建一个 pair 对象,它的两个元素分别是 T1 和 T2 ,其中 first 成员初始化为 v1,而 second 成员初始化为 v2。 
    make_pair(v1,v2); 以 v1 和 v2 值创建一个新 pair 对象,其元素类型分别是v1 和 v2 的类型。
    p1 < p2  两个 pair 对象之间的小于运算,其定义遵循字典次序:如果 p1.first < p2.first 或者 !(p2.first < p1.first) && p1.second < p2.second,则返回 true 。
    p1 == p2   如果两个 pair 对象的 first 和 second 成员依次相等,则这两个对象相等。该运算使用其元素的 == 操作符。
    p.first  返回 p 中名为 first 的(公有)数据成员。
    p.second 返回 p 的名为 second 的(公有)数据成员 。

     

  4. 涉嫌容器不提供front、push_front、pop_front、back、push_back以及pop_back操作;

  5. 要选择map对象,则必需包罗map头文件;
    定义map对象时,必须分别指明键和值的连串。map<string, int> word_count;

    map<k, v> m;                     创建一个名为 m 的空 map 对象,其键和值的类型分别为 k 和 v
    map<k, v> m(m2);  创建 m2 的副本 m,m 与 m2 必须有相同的键类型和值类型 
    map<k, v> m(b, e);  创建 map 类型的对象 m,存储迭代器 b 和 e 标记的范围内所有元素的副本。元素的类型必须能转换为 pair<const k, v> 

     

  6. 事关容器的键类型必得支持 < 操作符,并且该操作符应能“正确地干活”;

  7. map 定义的档案的次序

    map<K, V>::key_type                    在 map 容器中,用做索引的键的类型 
    map<K,V>::mapped_type 在 map 容器中,键所关联的值的类型 
    map<K,V>::value_type 一个 pair 类型,它的 first 元素具有 const map<K, V>::key_type 类型,而 second 元素则为 map<K, V>::mapped_type 类型 

    谨记: value_type 是 pair 类型,它的值成员能够修改,但键成员不可能改改。 

  8. 给 map 添新币素
    (1) 使用insert 成员贯彻;
    (2) 先用下标操作符获取成分,然后给拿走的要素赋值。

  9. 选择下标访谈 map 对象
    应用下标[i]拜会map中空头支票的成分将导致在map容器中增加一个新的因素,它的键即为该下标值;

  10. map::insert 的使用 

    m.insert(e) e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则插入一个值为 e.second 的新元素;如果该键在 m 中已存在,则保持 m 不变。该函数返回一个 pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素。
    m.insert(beg, end)                                                                        beg 和 end 是标记元素范围的迭代器,其中的元素必须为 m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在,则将该键及其关联的值插入到 m。返回 void 类型 。
    m.insert(iter,e)  e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则创建新元素,并以迭代器 iter 为起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具有给定键的元素。

     

  11. 搜索并读取 map 中的成分
    不修改 map 对象的询问操作:

    m.count(k)  返回 m 中 k 的出现次数
    m.find(k) 如果 m 容器中存在按 k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。

     

  12. 从map中删除成分

    m.erase(k)   删除 m 中键为 k 的元素。返回 size_type 类型的值,表示删除的元素个数 
    m.erase(p)  从 m 中删除迭代器 p 所指向的元素。p 必须指向 m 中确实存在的元素,而且不能等于 m.end()。返回 void 
    m.erase(b, e)                                                 从 m 中删除一段范围内的元素,该范围由迭代器对 b 和 e 标记。b 和 e 必须标记 m 中的一段有效范围:即 b 和 e 都必须指向 m 中的元素或最后一个元素的下一个位置。而且,b 和 e 要么相等(此时删除的范围为空),要么 b 所指向的元素必须出现在 e 所指向的元素之前。返回 void 类型 
  13. map 对象的迭代遍历
    与任何容器同样,map 一样提供 begin 和 end 运算,以扭转用于遍历整个容器的迭代器。比如,可正如将 map 容器 word_count 的从头到尾的经过输出:
    map<string, int>::const_iterator  map_it = word_count.begin();
    while (map_it != word_count.end())
     {
             cout << map_it->first << " occurs "  << map_it->second << " times" << endl;
             ++map_it;

    在使用迭代器遍历map 容器时,迭代器指向的成分按钮的升序排列。

  14. set

    map 容器是键-值对的联谊,set 容器只是只是的键的聚众。
    二种不一致满含:set 不支持下标操作符,并且从不概念 mapped_type 类型。
    在 set 容器中,value_type 不是 pair 类型,而是与 key_type 一样的门类。它们指的都是 set 中寄放的成分类型。与 map 同样,set 容器存款和储蓄的键也必得独一,并且无法改改。 

1、vector

那可不掌握,STL工作的器皿是在堆内开荒的一块新空间,而小编辈友好的变量一般寄存在函数栈或另一块堆空间中。为了能够统统调控STL自个儿的因素,为了能在融洽的势力范围随心干活,那就关系到复制。而一旦复制的靶子十分的大,由复制带来的质量代价也异常的大,对于大目的的操作,使用指针来代表对象能清除那上头的代价、

  1. multimap 允许贰个键对应三个实例。
    multimap不帮助下标运算,因为有个别键可能对应多个值;

  2. multimap添欧成分
    是因为键不须要是天下无双的,由此老是调用 insert 总会增添三个要素。

  3. multimap 删除成分 
    带有贰个键参数的 erase 版本将去除全体该键的具备因素,并赶回删除成分的个数。

  4. 在 multimap 和 multiset 中搜索成分
    涉及容器 map 和 set 的因素是按顺序存款和储蓄的。
    在 multimap 中,同三个键所关联的要素必然相邻寄存。

    方法一:使用 find 和 count 操作
    count 函数求出某键出现的次数,而 find 操作则重临一个迭代器,指向第七个具备正在搜索的键的实例:
    string search_item("Alain de Botton");
    typedef multimap<string, string>::size_type sz_type;
    sz_type entries = authors.count(search_item);
    multimap<string,string>::iterator iter = authors.find(search_item);
    for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter)
        cout << iter->second << endl; // print each title 
    率先,调用 count 明确某我所写的图书数目,然后调用 find 获得指向第一个该键所波及的因素的迭代器。for 循环迭代的次数正视于 count 重返的值。在特别处境下,假使 count 重临 0 值,则该循环永不奉行。

    措施二:独竖一帜的面向迭代器的消除方案 
    更优雅凝练的措施是选用两个从未见过的关联容器的操作:lower_bound 和 upper_bound。

    m.lower_bound(k) 返回一个迭代器,指向键不小于 k 的第一个元素 
    m.upper_bound(k)  返回一个迭代器,指向键大于 k 的第一个元素 
    m.equal_range(k)   返回一个迭代器的 pair 对象 它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k) 

    typedef multimap<string, string>::iterator authors_it;
    authors_it beg = authors.lower_bound(search_item),  end = authors.upper_bound(search_item);
    while (beg != end)

         cout << beg->second << endl; // print each title
         ++beg;

     

  1. multimap 允许三个键对应八个实例。
    multimap不协助下标运算,因为某些键只怕对应三个值;

  2. multimap添美成分
    由于键不供给是独一的,由此老是调用 insert 总会增添一个要素。

  3. multimap 删除成分 
    含有三个键参数的 erase 版本将去除全部该键的持有因素,并赶回删除成分的个数。

  4. 在 multimap 和 multiset 中检索成分
    关联容器 map 和 set 的要素是按顺序存款和储蓄的。
    在 multimap 中,同三个键所关联的成分必然相邻存放。

    方法一:使用 find 和 count 操作
    count 函数求出某键出现的次数,而 find 操作则重返三个迭代器,指向第一个具备正在查找的键的实例:
    string search_item("Alain de Botton");
    typedef multimap<string, string>::size_type sz_type;
    sz_type entries = authors.count(search_item);
    multimap<string,string>::iterator iter = authors.find(search_item);
    for (sz_type cnt = 0; cnt != entries; ++cnt, ++iter)
        cout << iter->second << endl; // print each title 
    第一,调用 count 鲜明某笔者所写的书籍数目,然后调用 find 获得指向第一个该键所关联的要素的迭代器。for 循环迭代的次数信赖于 count 重临的值。在特种意况下,假使 count 重临 0 值,则该循环永不试行。

    艺术二:独具匠心的面向迭代器的缓慢解决方案 
    更优雅凝练的法子是选取五个尚未见过的涉嫌容器的操作:lower_bound 和 upper_bound。

    m.lower_bound(k) 返回一个迭代器,指向键不小于 k 的第一个元素 
    m.upper_bound(k)  返回一个迭代器,指向键大于 k 的第一个元素 
    m.equal_range(k)   返回一个迭代器的 pair 对象 它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k) 

    typedef multimap<string, string>::iterator authors_it;
    authors_it beg = authors.lower_bound(search_item),  end = authors.upper_bound(search_item);
    while (beg != end)

         cout << beg->second << endl; // print each title
         ++beg;

     

vector初始化

初叶化方法

vector ilist1;

暗中认可起初化,vector为空, size为0,注解容器中尚无成分,并且 capacity 也回到 0,意味着还从未分配内部存款和储蓄器空间。这种开头化格局适用于元素个数未知,须求在程序中动态增加的意况。

: vector ilist2;

vector ilist2 = ilist;

两种办法等价 ,ilist2 起首化为ilist 的正片,ilist必得与ilist2 类型一样,也便是同为int的vector类型,ilist2将有所和ilist同样的体量和要素

: vector ilist = {1,2,3.0,4,5,6,7};

vector ilist {1,2,3.0,4,5,6,7};

ilist 起始化为列表瓜月素的正片,列表相月素必需与ilist的因素类型相容,本例中必得是与整数类型相容的种类,整形会向来拷贝,别的品种会开展类型转换。

: vector ilist3(ilist.begin()+2,ilist.end;

ilist3起始化为五个迭代器钦定范围桐月素的正片,范围中的成分类型必得与ilist3 的因素类型相容,在本例中ilist3被起先化为{3,4,5,6}。注意:由于只需要范围中的成分类型与待开端化的器皿的因素类型相容,因而迭代器来自不一致的器皿是可能的,举个例子,用二个double的list的限制来开端化ilist3是低价的。别的是因为构造函数只是读取范围中的元素实行拷贝,因而利用普通迭代器照旧const迭代器来提议范围并不曾分别。这种早先化方法特别符合于获取两个行列的子系列。

: vector ilist4;

暗许值先河化,ilist4旅长含有7个成分,每种元素实行缺省的值最早化,对于int,也正是被赋值为0,由此ilist4被开端化为含有7个0。当程序运营开始时代成分大概数量可预感,而要素的值供给动态获取的时候,可应用这种起头化方式。

:vector ilist5;

钦赐值开始化,ilist5被起首化为包涵7个值为3的int


2 只关乎到指针拷贝操作, 未有额外类的构造函数和赋值构造函数的调用;

vector复制vector

落到实处从vector1复制到vector2,实验证实,多样艺术都实现了内部存款和储蓄器上的复制

vectorvector2;

vectorvector3(vector1.begin(),vector1.end;

vectorvector4=vector1;

vectorvector5;
​ vector5.resize(vector1.size;
​ copy(vector1.begin(),vector1.end(),vector5.begin;

方法四,使用std::copy(),前一定对新的vector进行resize(),不然非常

不可取:

第11章 泛型算法      

第11章 泛型算法      

vector使用案例

    vector<int>vector1 {1,2,3,4};    cout<<"元数据:"<<" ";    for_each(vector1.begin(),vector1.end(),[]{cout<<x<<" ";});    //构造函数(container)    vector<int>vector2;    reverse(vector2.begin(),vector2.end;    vector2[1]=111;    cout<<endl<<"构造函数(container): ";    for_each(vector2.begin(),vector2.end(),[]{cout<<x<<" ";});    cout<<"元数据:"<<" ";    for_each(vector1.begin(),vector1.end(),[]{cout<<x<<" ";});    //构造函数(container.begin(),container.end    vector<int>vector3(vector1.begin(),vector1.end;    reverse(vector3.begin(),vector3.end;    vector3[1]=111;    cout<<endl<<"c.begin: ";    for_each(vector3.begin(),vector3.end(),[]{cout<<x<<" ";});    cout<<"元数据:"<<" ";    for_each(vector1.begin(),vector1.end(),[]{cout<<x<<" ";});    //赋值运算符重载=    vector<int>vector4=vector1;    reverse(vector4.begin(),vector4.end;    vector4[1]=111;    cout<<endl<<"赋值运算符重载= ";    for_each(vector4.begin(),vector4.end(),[]{cout<<x<<" ";});    cout<<"元数据:"<<" ";    for_each(vector1.begin(),vector1.end(),[]{cout<<x<<" ";});    //std::copy()    vector<int>vector5;    vector5.resize(vector1.size;    copy(vector1.begin(),vector1.end(),vector5.begin;    reverse(vector5.begin(),vector5.end;    vector5[1]=111;    cout<<endl<<"std::copy(): ";    for_each(vector5.begin(),vector5.end(),[]{cout<<x<<" ";});    cout<<"元数据:"<<" ";    for_each(vector1.begin(),vector1.end(),[]{cout<<x<<" ";});/*元数据: 1 2 3 4构造函数(container): 4 111 2 1 元数据: 1 2 3 4c.begin: 4 111 2 1 元数据: 1 2 3 4赋值运算符重载= 4 111 2 1 元数据: 1 2 3 4std::copy(): 4 111 2 1 元数据: 1 2 3 4*/

vecttor vt1;

     每一个泛型算法的落到实处都单身于独立的器皿,何况不依附于器皿存款和储蓄的因素类型。

     各种泛型算法的实现都独立于独立的容器,何况不信赖于器皿存储的因素类型。

vector的resize与reserve

reserve()函数为日前vector预留至中国少年共产党容纳size个因素的空间.(译注:实际空间也许大于size)

resize() 函数( void resize( size_type size, TYPE val ) )更改最近vector的深浅为size,且对新创建的因素赋值val
图片 1

(翻译:

调解容器大小以含有count成分。

假设当前高低大于count,则容器将被削减为其首先个count成分,就疑似重复调用pop_back()一样。

一经当前大小小于count,则附欧元素并用值的别本初阶化。)

resize和reserve函数本质都涉嫌了vector的内部存款和储蓄器存储空间,因为vector在内部存款和储蓄器中是接连寄存的,所以当resize的空间大于现存的蕴藏空间(capacity() 函数 重回当前vector在重新开展内存分配从前所能容纳的成分数量.)时,会另行选拔越来越大的半空中,并将装有因素复制过去。resize在初步化内部存款和储蓄器体积时有对值的初步化,由此此时push_back会发生size+1,内部存储器容积远远不足,重新寻觅更加大的内部存款和储蓄器空间并复制全体因素,所以这么些历程是很辛劳的。

vt1.push_bach(myBigObj);

     泛型算法须要选用迭代器,迭代器有如下供给:

     泛型算法需求接纳迭代器,迭代器有如下要求:

陈设测验

接下去斟酌插入的功能的实例,分别品尝在插入大数量3.8GB和小数目380MB时,各样情状的兑现。

push_back间接插入

敲定:费事,在插入的长河中,不断搜索“尊崇所”,不断“迁移大学本科营”,舟车劳苦效用低下

void testPushBack_bigsize(){    vector<int> vector1;    clock_t start = clock();    for (int i = 0; i < 1000000000; ++i) {//3814MB        vector1.push_back;    }    cout <<"共耗时:"<<  - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:42s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1073741824    clock_t start2 = clock();    vector1.push_back;    cout <<"共耗时:"<<  - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:0s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:1073741824}

先reserve在push_back

敲定:先分配空间再拓宽继续管理,能够使得的降低插入时间的消耗,耗费时间占原插入格局的53%到三分之一里面。

void testPushBack_byReserve_bigsize(){    vector<int> vector1;    vector1.reserve(1000000000);//3814MB    clock_t start = clock();    for (int i = 0; i < 1000000000; ++i) {        vector1.push_back;    }    cout <<"共耗时:"<<  - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:17s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1000000000    clock_t start2 = clock();    vector1.push_back;    cout <<"共耗时:"<<  - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:76s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:2000000000}void testPushBack_byReserve_smallsize(){    vector<int> vector1;    vector1.reserve(100000000);//381MB    clock_t start = clock();    for (int i = 0; i < 100000000; ++i) {        vector1.push_back;    }    cout <<"共耗时:"<<  - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:1s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:100000000 capacity:100000000    clock_t start2 = clock();    vector1.push_back;    cout <<"共耗时:"<<  - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:2s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:100000001 capacity:200000000}

先resize在使用坐标举办赋值

敲定:在分配空间时平昔对空中进行初步化,赋予初值,比相当的大进步了积攒的速率。可是在resize后举办push_back是不明智的挑选。

void testinsert_byResize_bigsize(){    vector<int> vector1;    vector1.resize(1000000000);    clock_t start = clock();    for (int i = 0; i < 1000000000; ++i) {        vector1[i]=i;    }    cout <<"共耗时:"<<  - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:3s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000000 capacity:1000000000    clock_t start2 = clock();    vector1.push_back;    cout <<"共耗时:"<<  - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:66s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:1000000001 capacity:2000000000}void testinsert_byResize_smallsize(){    vector<int> vector1;    vector1.resize(100000000);    clock_t start = clock();    for (int i = 0; i < 100000000; ++i) {        vector1[i]=i;    }    cout <<"共耗时:"<<  - start)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:0s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:size:10000000 capacity:10000000    clock_t start2 = clock();    vector1.push_back;    cout <<"共耗时:"<<  - start2)/ CLOCKS_PER_SEC <<"s"<<endl;//共耗时:2s    cout <<"size:"<<vector1.size() << " capacity:" << vector1.capacity() << endl;//size:10000001 capacity:20000000}

可取:

        •  扶助自增操作:从三个因素定位下三个因素
          •  提供解引用:访谈成分的值
          •  支撑相等和差别操作符:用于判别2个迭代器是还是不是相等 

        •  帮衬自增操作:从一个成分定位下八个因素
          •  提供解引用:访谈成分的值
          •  帮助相等和不一致操作符:用于判别2个迭代器是不是相等 

vector优化难点

严防reallocate内部存款和储蓄器,而招致的数目拷贝发生的额外耗费时间

vector在push_back的时候,假诺空间欠缺,会活动增加补充一些空间,若无留住的长空可用
就径直报名另一块可用的一而再的空间,把数据拷贝过去,然后删除旧空间,使用新空间
结果造功功效低下 。

能够经过以下三种组成来防止reallocate.

  1. vector::resize() 使用array index,效用最高,不过急需超前领略size大小

  2. vector::reserve()使用 push_back(),作用一般,较原生有肯定进步。

vecttor vt2;

 

 

3、hash_map

hash函数->间接地址,相比较函数->消除争辩

那五个参数刚好是我们在选用hash_map时供给钦定的参数.

hash_map<int, string> mymap;

等同于:hash_map<int, string, hash, equal_to > mymap;

#include <hash_map>#include <algorithm>#include <iostream>using namespace std;int main() {    __gnu_cxx::hash_map<int,string> mymap;    mymap[1]="风琴杨";    mymap[2]="林青霞";    if (mymap.find!=mymap.end        cout<<mymap[1]<<endl;    cout<<mymap[10]<<"  null"<<endl;    return 0;}//output/*风琴杨  null */

vt2.push_bach(new BigObj());

     “普通”的迭代器不修改基础容器的尺寸。算法恐怕会改换存款和储蓄在容器中的成分的值,恐怕会在容器内活动元素,然而,算法从不直接抬高或删除成分。 

     “普通”的迭代器不修改基础容器的尺寸。算法大概会转转移存入款和储蓄在容器中的成分的值,恐怕会在容器内运动元素,可是,算法从不直接抬高或删除成分。 

4、map

int main() {    string A ="anagram";    string B ="nagaram";    map<char,int> mymap1;    map<char,int> mymap2;    for (int i = 0; i < A.size {        mymap1[A[i]]++;        mymap2[B[i]]++;    }    bool flag = true;    //遍历一    for (int j = 0; j <min(mymap1.size(),mymap2.size {        int a = mymap1[A[j]];        int b = mymap2[A[j]];        if {            flag= false;            break;        }    }    //遍历二    map<char,int>::iterator it2 = map2.begin();    for (map<char,int>::iterator it = map1.begin();it!=map1.end(),it2!=map2.end(); ++it,++it2) {        if(it->second!=it2->second||it->first!=it2->first){            flag=0;            break;        }    }    cout<<flag<<endl;    return 0;}

//两数之和int main() {    int nums[]{2, 7, 11, 15};    int target = 9;    map<int,int> mymap;    for (int i = 0; i < sizeof/ sizeof; ++i) {        if(mymap.find(target-nums[i])!=mymap.end{            cout<<(*mymap.find(target-nums[i])).second<<" "<<i;            break;        }        else            mymap[nums[i]]=i;    }    return 0;}

增加和删除改查、multimap是二个key对应多少个值

class student{public:    int age;    string name;    string bjclass;    student(string _name,int _age, string _bjclass){        name = _name;        age = _age;        bjclass = _bjclass;    }    student(){}};void multimap_test(){    cout<<"---------------multimap--------------"<<endl;    student s1,s2,s3,s4,s5;    s1.name="s1";    s1.bjclass="se1161";    s2.name="s2";    s2.bjclass="se1161";    s3.name="s3";    s3.bjclass="se1162";    s4.name="s4";    s4.bjclass="se1162";    s5.name="s5";    s5.bjclass="se1162";    multimap<string,student> mymap2;    //    软件1161    mymap2.insert(make_pair("软件1161",s1));    mymap2.insert(make_pair("软件1161",s2));    mymap2.insert(make_pair("软件1161",s3));    //    软件1161    mymap2.insert(make_pair("软件1162",s4));    mymap2.insert(make_pair("软件1162",s5));    for (multimap<string,student>::iterator it =mymap2.begin(); it!=mymap2.end {        cout<<it->first<<"t"<<it->second.name<<endl;    }    int se1161nums = mymap2.count("软件1161");    int se1162nums = mymap2.count("软件1162");    cout<<"软间1161人数:"<<se1161nums<<endl;    cout<<"软间1162人数:"<<se1162nums<<endl;    //遍历所有软件1161的学生    multimap<string,student>::iterator it2 =mymap2.find("软件1161");    int flag = 0;    while (flag<se1161nums){        cout<<it2->first<<"t"<<it2->second.name<<endl;        it2++;        flag++;    }    cout<<"----------修改测试------------n";    //修改s3名称为ss3    for (multimap<string,student>::iterator it =mymap2.begin(); it!=mymap2.end {        if(it->second.name=="s3")            it->second.name="ss3";    }    for (multimap<string,student>::iterator it =mymap2.begin(); it!=mymap2.end {        cout<<it->first<<"t"<<it->second.name<<"t"<<it->second.bjclass<<endl;    }}int main() {    map<int,string> mymap1;    //插入方法1    pair<map<int,string>::iterator,bool> pair1 =mymap1.insert(pair<int,string>(1,"student1"));    if(pair1.second){        cout<<"key1插入成功n";    } else        cout<<"key1插入失败n";    mymap1.insert(pair<int,string>(2,"student2"));    //插入方法2    pair<map<int,string>::iterator,bool> pair2 = mymap1.insert(make_pair(1,"student3"));//若key已经存在则插入失败,返回pair的second为false    if(pair2.second){        cout<<"key2插入成功n";    } else        cout<<"key2插入失败n";    mymap1.insert(make_pair(4,"student4"));    //插入方法3    pair<map<int,string>::iterator,bool> pair3 = mymap1.insert(map<int,string>::value_type(5,"student5"));    if(pair3.second){        cout<<"key3插入成功n";    } else        cout<<"key3插入失败n";    mymap1.insert(map<int,string>::value_type(6,"student6"));    //插入方法4,若key已经存在会覆盖原值    mymap1[1]="student7";    mymap1[8]="student8";    for (map<int,string>::iterator it=mymap1.begin(); it !=mymap1.end {        cout<<.first<<":"<<.second<<" ";    }    cout<<endl;    cout<<"------------------查找测试------------------n";    map<int,string>::iterator it = mymap1.find;    if (it!=mymap1.end        cout<<"key:"<<it->first<<"  value:"<<it->second<<endl;    else        cout<<"key4不存在!"<<endl;    pair<map<int,string>::iterator,map<int,string>::iterator> pair4 = mymap1.equal_range;    cout<<"第一个迭代器的位置:"<<(*pair4.first).first<<"t"<<(*pair4.first).second    <<" n第二个迭代器的位置:" <<(*pair4.second).first<<"t"<<(*pair4.second).second<<endl;    cout<<"------------------删除测试------------------n";    while (!mymap1.empty{        auto it = mymap1.begin();        cout<<.first<<":"<<.second<<" ";        mymap1.erase;//根据迭代器删除    }    multimap_test();    return 0;}

注意事项:

  1. 头文件
    利用泛型算法必须富含 algorithm 头文件:
    #include <algorithm>
    标准库还定义了一组泛化的算术算法(generalized numeric algorithm),使用那个算准则必得带有 numeric 头文件:
    #include <numeric>  
  2. 只读算法
    (1) find
    vector<int> vec;
    ...

    int search_value = 42;
    vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value); 
    放置数组也足以选用迭代器和find完成查找
    int ia[6] = {27, 210, 12, 47, 109, 83};
    int search_value = 83;
    int *result = find(ia, ia + 6, search_value); 

    (2) count
    count在容器中找找有些值出现的次数
    int cnt = count(vec.begin(), vec.end(), search_value);

  1. 头文件
    使用泛型算法必得含有 algorithm 头文件:
    #include <algorithm>
    标准库还定义了一组泛化的算术算法(generalized numeric algorithm),使用这个算法规必须包蕴 numeric 头文件:
    #include <numeric>  
  2. 只读算法
    (1) find
    vector<int> vec;
    ...

    int search_value = 42;
    vector<int>::const_iterator result = find(vec.begin(), vec.end(), search_value); 
    放置数组也得以应用迭代器和find达成查找
    int ia[6] = {27, 210, 12, 47, 109, 83};
    int search_value = 83;
    int *result = find(ia, ia + 6, search_value); 

    (2) count
    count在容器中搜索有些值出现的次数
    int cnt = count(vec.begin(), vec.end(), search_value);

TAG标签:
版权声明:本文由必威发布于必威-编程,转载请注明出处: 每个泛型算法的实现都独立于单独的容器, 每