电子商务网站建设与维护意味着什么,怎样找家做网站的公司,c语言也能干大事网站开发,怎么做网站支付前言 知识点很多#xff0c;这里只记录遗忘的。从这章开始会对前面章节的内容进行一个扩充#xff0c;如果以前的忘了读起来会有点吃力。总的来说#xff0c;本章节难度不大。 文章目录一、概述二、容器库概览2.1容器定义和初始化2.2赋值三、顺序容器操作3.1添加元素3.2删除…前言 知识点很多这里只记录遗忘的。从这章开始会对前面章节的内容进行一个扩充如果以前的忘了读起来会有点吃力。总的来说本章节难度不大。 文章目录一、概述二、容器库概览2.1容器定义和初始化2.2赋值三、顺序容器操作3.1添加元素3.2删除元素3.3forward_list3.4容器操作使迭代器失效四、vector对象是如何增长的五、string操作5.1构造string 的其他方法5.2改变string的其他方法5.3string搜索操作5.4compare函数5.5数值转换六、容器适配器 一、概述
顺序容器一共有六种类型vector、deque、list、forward_list、array、string。下图是它们的一些特性。除了固定大小的array外其他容器都提供高效、灵活的内存管理。vector、string和array之所以支持快速随机访问是因为它们的元素存储在连续的内存空间中所以进行插入删除操作就会很慢。而forward_list和list正好相反它们存储元素的内存空间都是离散的因此访问元素的开销较大。deque相对来说访问速度和某些情况的插入删除操作都比较高效。
array和forward_list都是C11增加的新特性。array相对内置数组效果更高、更安全。forward_list设计是为了达到与手写单向链表的性能。新标准库的容器优于旧版本。 二、容器库概览
2.1容器定义和初始化
将一个新容器创建为另一个容器的拷贝的方法1直接拷贝整个容器(两个容器的类型必须相同)2拷贝一个由迭代器指定的元素范围array除外两个迭代器的类型可以不同只要元素能够转换 与顺序容器大小相关的构造函数
如果元素类型是内置类型或者是具有默认构造函数的类类型可以只为构造函数提供一个容器大小参数。如果元素没有默认构造函数除了大小参数外还必须指定一个显式的元素初始值。
array
array与内置数组很相似当定义一个array时除了指定元素类型还要指定容器大小。
arrayint, 42
arraystring, 10一个默认构造的array是非空的如果我们对array进行列表初始化初始值的数目必须等于或小于array的大小。内置数组不能对其进行拷贝或对象赋值操作但是array没有限制
int d[3] {1,2,3};
int c[3] d[3]; // 错误
arrayint, 3 d2 {1,2,3};
arrayint, 10 c2 d2;2.2赋值
赋值就是把左边容器的元素全部换成右边容器中元素的拷贝。只有顺序容器可以使用assign但是array不支持assign操作。 assign
赋值运算符要求等号两边的运算对象具有相同的类型assign允许从一个不同但相容的类型赋值或者从容器的一个子序列赋值。使用assign会使左边容器内部的迭代器、引用和指针失效
swap
swap交换两个相同类型容器的内容除string外指向容器的迭代器、引用和指针在swap操作之后都不会失效。swap两个array会正在交换它们的元素
三、顺序容器操作
3.1添加元素
除了array所有标准库容器都提供灵活的内存管理。下表是添加元素的的操作。前面提到像vector、string等容器添加一个元素可能会导致整个对象的存储空间重新分配所以当我们使用这些操作时必须记得不同容器使用不同的策略来分配元素空间。 当我们将一个对象插入到容器时实际上放入的是对象的拷贝容器的元素与提供值的对象之间没有任何关联。
emplace
C11引入了三个新成员emplace_front、emplace、emplace_back前面说了以前的插入元素的方法是拷贝而这些新成员会进行构造不会拷贝。下面一段代码很容易理解它们之间的差别。加入有一个info对象它含有三个数据成员且对应的构造函数。在使用emplace_back我们可以在A的末尾添加一个Info对象但是push_back却不行因为它是拷贝元素对于push_back的函数设计里面没有接收三个参数的版本所以只能写成最后一行的形式先构造再拷贝。总之emplace_back直接进行构造简化了操作过程。当然如果Info对象没有对应三个参数的构造函数那么该操作也会失效。
A.emplace_back(heyun,12,23);
A.push_back(heyun,12,23); // 错误
A.push_back(Info(heyun,12,23));3.2删除元素
下标是删除元素的操作。 3.3forward_list
有C语言基础的应该都记得链表forward_list其实就是一个单向链表。它的特殊之处在于进行添加和删除元素时删除或添加的元素之前的那个元素的后继会发生改变。 下表是forward_list特有的插入和删除元素操作。 3.4容器操作使迭代器失效
添加元素
vector和string如果存储空间被重新分配指向容器的迭代器、指针和引用都会失效。如果没有重新分配则指向插入元素之间的有效之后的全部失效。deque除了在首尾之外的任何位置插入元素会让它们都失效如果在首尾添加元素迭代器会失效但指向存在的元素的引用和指针不会失效list和forward_list全部都有效
删除元素
list和forward_list指向容器其他位置的迭代器全部都有效deque在首尾之外的任何位置删除元素指向被删除元素之外其他元素的迭代器、引用或指针也会失效。如果删除的是尾元素则尾后迭代器也会失效但是其他迭代器、引用和指针不受影响。如果删除首元素这些都不受影响vector和string指向被删除元素之前的有效。只要删除元素尾后迭代器总是失效。
四、vector对象是如何增长的
第一次接触vector时就很好奇这个和数组类似的存储容器居然有和链表一样的动态增加容量的功能。我们知道vector为了支持快速随机访问里面的元素是连续存储的如果这时vector的空间不足以接纳新的元素可以再开辟一段连续的空间就旧元素和新元素一起拷贝进去最后删除旧的空间。这样虽然能够达到目的但是经常进行性能会非常之慢。
C标准库为了避免这种代价设法减少容器空间重新分配次数的策略。当不得不获取新的内存空间时vector和string的实现通常会分配比新的空间需求更大的内存空间。
我们可以人为的去管理容量的成员函数。对于reserve只有当前需要的内存空间超过当前容量时才会改变vector的容量。 五、string操作
这一小节主要对第三章的string内容进行一个补充。
5.1构造string 的其他方法 5.2改变string的其他方法
string类型同样支持顺序容器的赋值运算符及assign、insert和erase操作。
s.insert(s.size(),5,!); // 在s末尾插入5个感叹号
s.erase(s.size() - 5,5); // 在s删除最后5个字符const char *cp Stately, plump Buck;
s.assign(cp,7); // s Stately
s.insert(s.size(), cp 7); // s Stately, plump Buck assign总是替换string中的所有内容append总是将新字符追加到string末尾
5.3string搜索操作
string类提供了6个不同的搜索函数每个函数都有4个重载版本如下表所示。每个搜索操作会返回一个string::size_type值表示匹配发生位置的下标如果搜索失败会返回一个名为string::npos的static成员。两个搜索操作的返回值类型都是一个unsigned类型所以不要用带符号类型进行接收。 下面写几个书上的例子
string name(AnnaBelle);
auto pos1 name.find(Anna); // pos1 0// 查找给定字符串中任何一个字符匹配的位置
string numbers(0123456789), name(r2d2);
auto pos name.find_first_of(numbers);
string dept(1231p23);
auto pos dept.find_first_not_of(number); // 返回p的下标5.4compare函数 5.5数值转换
C11引入多个函数可以实现数值数据与标准库string之间的转换。 六、容器适配器
stack、queue和priority_queue是三个顺序容器适配器。一个适配器是一种机制能使某种事物的行为看起来像另外一种事物一样。 定义一个适配器
每个适配器都定义两个构造函数默认构造函数创建一个空对象接受一个容器的构造函数拷贝该容器来初始化适配器。stack和queue基于deque实现priority_queue在vector的基础上实现。
stackint stk(deq); // 从deq拷贝元素到stk
stackstring, vectorstring str_stk; // 在vector上实现的空栈所有适配器都要求容器具有添加和删除元素的能力所以array不适用于适配器。同理forward_list也不行。
stack只要求push_back、pop_back和back因此可以使用除array和forward_list之外的任何容器类型来构造stack。
queue要求back、push_back、front和push_front因此可以构造于list或deque之上但不能基于vector构造。
priority_queue除了front、push_back和pop_back操作之外还要求随机访问能力可以构造于vector或deque之上不能基于list构造。
栈适配器 队列适配器
priority_queue允许为队列中的元素建立优先级也就是每个元素含有一个权重权重大的会优先排在前面。