新概念:迭代器、容器索引和迭代器失效
迭代器也是一种自定义类对象。但它本身在数据结构中具有一定的语义,它是用来访问、遍历某种数据结构的工具。对于我们的容器而言,它就是一种访问容器的接口。根据对容器的访问权限(读、写)分为两种迭代器:const迭代器和非const迭代器。前面已经讲过const语义了,所以很容易想到const迭代器是用来对容器做只读操作的。
前面我们都使用索引去访问我们的容器,现在认识了迭代器,我们就又多了一种访问容器的方法了。容器在被操作的时候,其内部数据可能会发生变化,比如增加或减少。这样的话,我们的容器的索引和迭代器都有可能失效。比如我们有一个std::vector容器,它有1个元素,此时索引0和迭代器vec.begin()都是关联着这个唯一的元素的。当我们将这个元素删除的时候,那么索引0和迭代器vec.begin()都将失效。一般来说、对容器的写操作都可能会引发某些迭代器和索引失效,我们应该对容器的特性以及操作引发的副作用都要认真的去了解,那样才能正确且安全的对我们的容器进行访问。
新设施:std::list、isspace、
std::list和std::vector一样都是标准库提供的容器。但是他们是两种不同的数据结构。std::vector具有连续存储的性质,而std::list则没有。教材中使用std::list去优化我们的代码,是利用了std::list对元素的高效删除和插入操作。
isspace是一个C函数,C++将一些C库函数放到<cctype>头中提供给我们使用。这个函数是判断一个字符是否是空白字符的函数,如果是则返回true,否则返回false。
新技术:使用迭代器代替索引、容器erase返回的迭代器、根据数据结构特性选择、根据语义去理解
标准库中容器不是都支持索引的,但是却都支持迭代器,所以我们使用迭代器代替索引会让我们的代码更具有扩展性,并且我们的标准库容器算法均提供对迭代器的支持,而非索引。
容器中erase操作是会引发一定的迭代器失效的(根据不同的数据结构而言影响的地方有所不同,但是都会影响到当前迭代器)。但是这个操作在标准库中具有一个统一的语义,它将返回被删除位置(当前迭代器)的下一个位置的迭代器。所以教材中使用了这个返回值来保证我们的循环能正确的遍历容器。
教材中用std::list替换std::vector让我们看到了程序在效率上得到的提升,这说明了我们在选择数据结构的时候要根据我们的程序对容器的操作以及容器具有的特性来做出取舍。虽然可能多种容器都能完成我们的工作,但不是每个容器都是最适合我们当前程序的。
教材中有++iter;这样的代码。这个迭代器在不同的容器中引发的操作可能会是不同的,但是它们的语义是相同的:将这个迭代器移动到当前关联的元素的下一个元素进行关联。所以我们在使用它的时候不必去考虑到底它是内存中一个元素大小的偏移,还是一个指针的跳转。只要理解其语义来使用,那就足够了。这不仅仅表现在迭代器中,对于我们的任何抽象我们都应该用语义去理解它,让我们离那些实现细节远一些!
下一课:C++课堂第6章 使用库算法 希望我的课堂对大家学习C++有所帮助