//一个容器就是一些特定类型对象的集合。
//顺序容器,为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值
//而是与元素加入容器时的位置相对应。
//9.1顺序容器概述
//标准库中的顺序容器如下:
//vector 可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。
//deque 双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。
//list 双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
//forward_list 单向链表。只支持单项顺序访问。在链表任何位置进行删除/插入操作速度都很快。
//array 固定数组。支持快速随机访问,不能添加或删除元素。
//string 与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快。
//选择容器的基本原则
//1.除非你有很好的理由选择其他容器,否则用vector
//2.如果你的程序有很多小的元素,且空间额外开销很重要,则不要使用list或forward_list。
//3.如果程序员要求随机访问元素,应使用vector或deque
//4.如果程序需要在头部位置插入或删除元素,但不会再中间位置进行插入或删除操作,则使用deque
//5.如果程序员只有输入时才需要在容器中间插入元素,随后需要随机访问元素,则:
//一:首先,确定是否真的需要在容器中间位置添加元素。当处理输入数据时,通常可以很容易的向vector追加数据,然后调用标准库函数sort函数
//来重排容器中的元素,从而避免在中间位置添加元素。
//二:如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。
//9.2容器库概览
//9.2.1迭代器
//与容器一样,迭代器有着公共的接口:如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的。
//不支持--运算符
//支持string、array、vector、deque。
//迭代器范围
//一个迭代器的范围由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置
//通常称为begin和end,或者是first和last
//左闭右开
//9.2.2容器类型成员
//iterator 此容器类型的迭代器类型
//const_iterator 可以读取元素,但不能修改元素的迭代器类型
//size_type 无符号整数类型,足够保存此容器类型最大可能容器的大小
//difference_type带符号整数类型,足够保存两个迭代器之间的距离
//value_type 元素类型
//reference 元素的左值类型;即value_type&
//9.2.3begin和end成员
//begin和end有很多中版本,带r的为反向迭代器,带c的为const迭代器。
//9.2.4容器定义和初始化
//每个容器类型都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创建一个指定类型的空容器。
//且都可以接受指定大小和元素初始值的参数。
//将一个容器初始化为另一个容器的拷贝
//要求:两个容器的类型及其元素类型必须匹配。不过,当传递迭代器参数来拷贝一个范围时,就不要求容器类型是相同的了。
//而且,新容器和原容器中的类型也可以不同,只要能将要拷贝的元素转换为要初始化的容器的元素类型即可。
/*
list<string> authors={"milton","shakespeare","austen"};
vector<const char*> articles={"a","an","the"};
list<string> list2(authors);//正确,类型匹配
deque<string> authilist(authors); //错误:容器类型不匹配
vector<string> words(articles);//错误:容器类型必须匹配
forward_list<string> words(articles.begin(),articles.end());//正确:可以将const char* 元素转换为string
*/
//列表初始化
//与顺序容器大小相关的构造函数
//标准库array具有固定大小
//9.2.5赋值和swap
//9.2.6容器大小操作
//除了一个例外,每个容器类型都有三个与大小相关的操作。成员函数size(参加3.2.2节,第78页)返回容器中元素的数目;
//empty当size为0时返回布尔值true,否则返回false;max_size 返回一个大于或等于该类型容器所能容纳的最大元素的值。
//9.2.7关系运算符
//类似string比大小
//9.3顺序容器操作
//9.3.1向顺序容器添加元素
//forward_list 有自己专有版本的insert和emplace
//forward_list 不支持push_back和emplace_back。
//vector不支持push_front和emplace_front。
//c.push_back(t)或c.emplace_back(args) //在c的尾部创建一个值为t或args创建的元素,返回void
//c.push_front(t)或c.emplace_front(args)//在c的头部创建一个值为t或args创建的元素,返回void
//c.insert(p,t) 或c.emplace_front(args)//在迭代器p指向的元素之前创建一个值为t或由args创建的元素。返回只想新添加的元素的迭代器。
//c.insert(p,n,t) 在迭代器p指向的元素之前插入n个值为t的元素。返回指向新添加的第一个元素的迭代器;若n为0,则返回p
//c.insert(p,b,e) 将迭代器b和e指定的反问欸的元素插入到迭代器p指向的元素之前。b和e不能指向c中的元素。返回指向新添加的第一个元素的迭代器;
//c.insert(p,il) il是一个花括号包围的元素值列表。将这些给定值插入到迭代器p指向的元素之前。返回指向新添加的第一个元素的迭代器,若列表为空,则返回p
//9.3.2访问元素
//at和下标操作只适用于string、vector、deque、和array。
//back操作不适用于forward_list
//c.back() 返回c中尾元素的引用。若c为空,函数行为未定义
//c.front() 返回c中首元素的引用。若c为空,函数行为未定义
//c[n] 返回c中小标为n的引用。
//c.at(n) 返回c中小标为n的引用。
//9.3.3删除元素
//与添加元素的多种方式类似,(非array)容器也有多种删除元素的方式。
//forward_list有特殊版本的erase
//forward_list不支持pop_back; vector和string不支持pop_front.
//c.pop_back() 删除c中尾元素。若c为空,则函数行为未定义。函数返回void
//c.pop_front() 删除c中首元素。若c为空,则函数行为未定义。返回void
//c.erase(p)删除迭代器p所制定的元素,返回一个指向被删元素之后的迭代器,若p指向尾元素,则返回尾后迭代器。
//若p是尾后迭代器,则函数行为未定义
//c.erase(b,e) 区间删除,返回指向最后一个被删除之后元素的迭代器。
//c.clear() 删除c中所有元素。
//9.3.4特殊的forward_list操作
//9.3.5改变容器的大小resize函数
//9.3.6容器操作可能使迭代器失效
//9.4vector对象是如何增长的
//管理容量的成员函数
//c.shrink_to_fit()请将capacity()减少为size()相同大小
//c.capacity() 不重新分配内存空间的话,c可以保存多少元素
//c.reserve(n) 分配至少能容纳n个元素的内存空间。
//理解capacity和size
//size是指容器已经保存的数目,capacity是不分配新的内存空间的前提下它最多可以保存多少元素。
//下面的代码展示了size和capacity之间的相互作用。
#include "iostream"
#include "vector"
#include "string"
using namespace std;
int main91() {
vector<int> a = { 1,1,1,1,1 };
cout << a.size();
cout << " " << a.capacity();
cout << ends;
a.push_back(2);
cout << a.size();
cout << " " << a.capacity();
system("pause");
return 0;
}
//9.5额外的string操作
//9.5.1构造string的其他方法
//string s(cp,n) s是cp指向的数组中前n个字符的拷贝,次数组至少应该包含n个字符
//string s(s2,pos2) s是string s2从下标 pos2 开始的字符的拷贝。若pos2>s2.size(),构造函数的行为未定义
//string s(s2,pos2,len2) s是string s2从下标开始pos2开始len2个字符的拷贝。若pos2>s2.size(),构造函数的行为未定义。不管len2的值是多少,
//构造函数之多拷贝s2.size()-pos2个字符。
//substr操作
//string s("hello world");
//string s2 = s.substr(0, 5);//s2=hello
//string s3 = s.substr(6);//s3=world
//string s4 = s.substr(6, 11);//s4=world
//string s5 = s.substr(12);//抛出一个out_of_range异常
//9.5.2改变string的其他方法
//append和replace函数
//9.5.3string的搜索操作
//string类提供了6个不同的搜索参数,每个参数都有4个重载版本。
//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
//s2,pos
//cp,pos
//cp,pos,n
//9.5.4compare函数,比较大小,类似关系运算符。
//9.5.5数值转换
int main92() {
int i = 42;
cout << i;
cout << endl;
string s = to_string(i);
cout << s << endl;
double d = stod(s);
cout << d << endl;
s = i;
cout << " " << s << endl;;
system("pause");
return 0;
}
//9.6容器适配器
//除了顺序容器外,标准库还定义了三个顺序容器适配器
//stack(先进后出),queue(先入先出),priority_queue(按优先级)。
//适配器是标准库中的一个通用概念。容器、迭代器和函数都有适配器。本质上,一个适配器是一种机制,能使某种事物的行为看起来像是另外一件事物一样。
//一个容器适配器接受一种已有的容器类型,使其行为看起来像一种不同的类型。
C++Primer 学习笔记 第九章 顺序容器
最新推荐文章于 2024-08-16 08:17:29 发布