C++程序设计:原理与实践(进阶篇)15.8 调整vector类达到STL版本的功能

15.8 调整vector类达到STL版本的功能


在15.5节中为vector增加了begin()、end()和类型别名后,现在只差insert()和erase()就接近我们设计一个std::vector的近似版本的目标了:

 

我们还是使用指向元素类型的指针T*作为迭代器的类型,这是最简单的方法。我们将边界检查迭代器的实现留作练习(习题18)。

人们通常不会为元素连续存储的数据类型(如vector)提供列表操作,如insert()或erase()。但insert()和erase()这样的列表操作对短vector或少量元素极为有用也极为高效。我们已经反复看到了push_back()的作用,它是另一个常见的列表操作。

基本上,我们可以通过拷贝所有位于所删除元素之后的元素来实现vector<T,A>::erase()。利用14.3.6节中定义的vector再加上上述内容,我们得到:

 

借助下面的图示,你可以更容易理解上面代码:

 

erase()的代码非常简单,但在纸上试着画几个例子可能是个好主意。有没有正确地处理空vector?为什么要判断p==end()?如果删除vector的最后一个元素会怎么样?如果使用下标语法的话代码的可读性会不会更好?

相对而言,vector<T, A>::insert()就有一点复杂了:

 

 

请注意:

由于迭代器不能指向序列之外,所以我们使用指针来完成,比如elem+sz。这就是为什么分配器用指针而不是迭代器来定义。

当我们使用reserve()时,元素会被移动到一块新的内存中。因此,我们必须要记住插入元素位置的索引,而不是指向它的迭代器。当vector为其元素重新分配内存时,指向vector内部的迭代器会失效——可以理解为它们指向的是旧的内存。

我们使用分配器参数A的方式很直观,但不准确。当你需要实现一个容器时,最好还是仔细读一下相关的标准。

由于这些微妙的细节,我们尽量避免处理底层内存问题。自然地,标准库vector(以及所有其他标准库容器)能正确实现这些重要的语义细节。这也是优先使用标准库而不是“家庭制作”的原因之一。

出于性能原因,你不应在一个含有100?000个元素的vector内部使用insert()或erase();对这种操作,使用list(或map,参见16.6节)更为适合。但是,vector确实提供了insert()和erase()操作,而且如果我们只是移动几个或几十个字的数据的话,其性能是没有问题的——毕竟现代计算机已非常擅长这种拷贝操作(见习题20)。注意不要用list(链表)表示少量元素的列表。

时间: 2024-10-24 21:14:05

C++程序设计:原理与实践(进阶篇)15.8 调整vector类达到STL版本的功能的相关文章

C++程序设计:原理与实践(进阶篇)15.9 调整内置数组达到STL版本的功能

15.9 调整内置数组达到STL版本的功能 我们之前反复指出内置数组的不足之处:它们动不动就会隐式转换成指针,它们不能通过赋值操作进行拷贝,它们不知道自己的大小(见13.6.2节),等等.我们也指出了它们最大的优点:它们近乎完美地利用了物理内存. 为了综合二者之长,我们可以创建一个具有数组优点而没有其不足的array容器.array的一个版本已经作为技术报告的一部分引入C++标准中.由于技术报告中的特性并不要求所有C++实现都必须包含,因此你所使用的实现可能并不包含array.但其思路是简单有用

c++-关于《C++程序设计原理与实践》第3章例子的一个问题

问题描述 关于<C++程序设计原理与实践>第3章例子的一个问题 本人菜鸟,现正在学习C++.<C++程序设计原理与实践>第3章有一个例子,代码如下: #include #include #include #include #include using namespace std; inline void keep_window_open(){ char ch; cin >> ch; } int main() //C++ Programs start by executi

源代码-C++程序设计原理与实践

问题描述 C++程序设计原理与实践 #include "std_lib_facilities.h" int main() { cout<<"Hello,world!n"; return 0; } 我下了源代码,放到那里才能猜VC98编译时不出错?最好详细点,带有图解 解决方案 ...大哥,都什么年代了还用98

15.9 调整内置数组达到STL版本的功能

15.9 调整内置数组达到STL版本的功能 我们之前反复指出内置数组的不足之处:它们动不动就会隐式转换成指针,它们不能通过赋值操作进行拷贝,它们不知道自己的大小(见13.6.2节),等等.我们也指出了它们最大的优点:它们近乎完美地利用了物理内存. 为了综合二者之长,我们可以创建一个具有数组优点而没有其不足的array容器.array的一个版本已经作为技术报告的一部分引入C++标准中.由于技术报告中的特性并不要求所有C++实现都必须包含,因此你所使用的实现可能并不包含array.但其思路是简单有用

《 C++程序设计:原理与实践(进阶篇.》导读

本节书摘来自华章出版社< C++程序设计:原理与实践(进阶篇)>一书中作者[美] 本贾尼·斯特劳斯特鲁普(Bjarne Stroustrup) 著 刘晓光 李忠伟 王刚 译     前 言 Programming: Principles and Practice Using C++, Second Edition 该死的鱼雷!全速前进. --Admiral Farragut 程序设计是这样一门艺术,它将问题求解方案描述成计算机可以执行的形式.程序设计中很多工作都花费在寻找求解方案以及对其求精上

C++程序设计:原理与实践(进阶篇)15.6 实例:一个简单的文本编辑器

15.6 实例:一个简单的文本编辑器 列表最重要的性质就是可以在不移动元素的情况下对其进行插入或删除操作.下面我们通过一个例子来说明这一点.考虑应该如何在文本编辑器中表示一个文本文件中的字符.所选用的表示方式应当能够使对文本文件进行的操作简单而高效. 那么具体会涉及哪些操作呢?假设文件能存储在计算机的内存中.也就是说,我们可以选择任何一种适合的表示方式,当需要保存到文件中时,只要把它转换成一个字节流就可以了.相应地,我们也可以把一个文件中的字符转成字节流,从而把它读入内存中.这说明我们只需要选择

C++程序设计:原理与实践(进阶篇)15.5 再次泛化vector

15.5 再次泛化vector 显然,通过15.3-15.4节的例子我们发现,标准库vector包含一个iterator成员类型,以及begin()和end()成员函数(与std::list类似).然而,我们并没有在第14章中为vector类提供这些成员.那么,对于不同类型的容器而言,它们究竟采用了什么方法,以使它们或多或少地能够在15.3节所介绍的STL泛型编程风格中相互替换使用?首先,我们将简要介绍一种解决方案(简单起见,我们忽略了分配器),然后再对解决方案进行解释:       using

C++程序设计:原理与实践(进阶篇)15.7 vector、list和string

15.7 vector.list和string 为什么我们对行用list而对字符用vector呢?更准确地说,我们为什么要用list保存行的序列而用vector保存字符序列呢?再有,为什么不用string来存储一行呢? 我们可以把这些问题再一般化一些.到现在为止,我们知道了四种存储字符序列的方法: char[](字符数组): vector<char>: string: list<char>. 那么对于一个给定问题应该采取哪种存储方式呢?当问题非常简单时,选择哪种方式都无所谓,因为它

C++程序设计:原理与实践(进阶篇)16.5 数值算法

16.5 数值算法 大多数的标准库算法都涉及处理数据管理问题:它们需要对数据进行拷贝.排序.查找等.但是,只有少数算法涉及数值计算.当我们需要进行计算时,这些数值算法就变得十分重要了,并且这些算法为我们在STL框架中编写数值算法提供了范例. 在STL标准库中只有四种数值算法: 数值算法 x = accumulate(b,e,i) 累加序列中的值:例如,对{a, b, c, d}计算i+a+b+c+d.结果x的类型与初始值i的类型一致 x = inner_product(b,e,b2,i) 将两个