2.3.1. 需要修改迭代器精化的分类么
在理想的世界,我们希望有更丰富的迭代器分类。在下一章中,我们将讨论迭代器的一个独立特性——元素引用类别。在STL扩展这个更广阔的世界中,考虑围绕着基本主题出现的区别,我们可能会想到更多正交特性。对这些特性的争论可能是无休止的。虽然我们可以很简单地通过现有概念中的特性来描述这些特性(在41章中我们将看到怎么用现有概念中的特性推断出元素引用类别),但这样做并没有任何技术优势,况且这些附加特性的概念会使问题更容易理解。举例来说,我们可以用术语“常量前向迭代器”或者“不可变可复制单向迭代器”来指代同一个类型,您认为哪个更好理解一点呢?呈几何级数增长的特性数目,很可能会(对更好地进行迭代器分类)起反作用,且不说C++(www.cppentry.com)使用者们可能很难就“依据哪些特性进行分类”达成一致。话说回来,以上这些只是探讨而已,标准已经是这个样子了,我们不能期望如此激进地改变像迭代器这样的基本概念了。
虽说如此,为了清晰,我还是在本书中使用了两个新术语。讨论输入迭代器的时候,我会使用“只读一次性语义”这样的表述,以强调该迭代器类型在任何时候都被限于在一个区间上只有一个活动实例。另一个新术语指代对随机访问迭代器概念的一个精化,称为连续迭代器概念。简单来说,它具有所有随机访问迭代器的所有特性,此外该类型所有实例还都必须满足以下要求:
这个关系和我在1.3.5节中提到的关系完全一样,在那里这是区分随机访问迭代器和指针的关键。但需要注意的是不是并非所有连续迭代器的都是指针,重载了取址操作符的类型都可能满足该关系。(我在Imperfect C++(www.cppentry.com)第26章中强烈反对这样的做法,但尽管如此,有时候使用该技巧也是很有用的,在本书附赠CD上的的附加章节《小心非指针连续迭代器》中,我们会看到这种迭代器在一种编译器标准库中被使用的例子。我们也会看到它给扩展STL的程序员带来的麻烦和解决该问题的方法。
你可能不明白为什么这个新增的精化很重要。在标准库里,只有std::vector可以称得上提供了连续迭代器。(注意这里没有包括std::valarray,我不是专注于数值计算的程序员,所以我可能忽视了它们之间的细微差别,但是对我来说valarray如此的差劲和可厌,如果比较哪种“曾经看上去貌似是个好主意”的程度,只有std::vector<bool>比valarray更差一些。也许你不知道,valarray上的==操作符并不返回它两端的操作数的相等与否,而是返回一个valarray<bool>的实例,其中的元素指出两个操作数的对应元素是否相等!不管valarray是好是坏,在本书中我们都不会讨论它。)
在标准库之外,STL扩展的世界里,存在更多和扩展集合相关联的连续迭代器。使用连续迭代器这个术语强调了这些集合的这一特性,并且强调了随机访问迭代器和指针(以及和指针等价的、重载了取址操作符operator &()的类)之间的区别。用连续迭代器代表的连续区间,和接受指针参数的函数兼容。考虑下列值类型为V的随机访问迭代器RI区间和连续迭代器CI区间:
RI r_begin = . . . RI r_end = . . . CI c_begin = . . . CI c_end = . . .
|
以及函数use_V():
void use_V(V* pv, size_t n);
|
假设[r_begin, r_end)和[c_begin, c_end)非空,那么下列表达式是有意义的:
use_V(&*c_begin, c_end - c_begin);
|
但以下这句却是错误的:
use_V(&*r_begin, r_end - r_begin); |
我们在本书第二、第三部分中,将看若干关于这两类精化之间的重要区别的例子。
【责任编辑:
董书 TEL:(010)68476606】