在 advance() 和 distance() 函数各自的功能和用法基础上,继续讲解如何利用这 2 个函数实现将 const_iterator 迭代器转换为 iterator 迭代器,或者将 const_reverse_iterator 迭代器转换为 reverse_iterator 迭代器。
注意,上面提到的 iterator、const_iterator、reverse_iterator 和 const_reverse_iterator 是 C++ STL 标准库提供了 4 种基础迭代器,关于它们各自的特性和功能可以阅读 《C++ STL迭代器》一节,这里不再重复赘述。
要知道,C++ STL标准库为了方便用户更轻松地操作容器,每个容器的模板类都提供有丰富且实用的方法。在这些方法中,有些是以 const_iterator 类型迭代器作为参数,也就意味着在使用此类方法时,需要为其传入一个 const_iterator 类型的迭代器。
例如,vector 容器模板类中提供有 insert() 方法,该方法的语法格式如下:
iterator insert (const_iterator position, const value_type& val);
注意,此方法有多种语法格式,这里仅列举了其中的一种。有关该方法的具体用法,可阅读《C++ STL vector插入元素》一节。
本文作者原创,转载请附上文章出处与本文链接。
如果想调用此格式的 insert() 方法,就需要为其传入一个 const_iterator 类型的迭代器。例如:
#include
#include
using namespace std;
vectorvalue{ 1,2,3,4,5 };
//定义一个 const_iterator 类型的迭代器
vector::const_iterator citer = value.cbegin();
value.insert(citer, 10);
for (auto iter = value.begin(); iter != value.end(); ++iter) {
cout << *iter << " ";
}
显然通过调用 insert() 方法,并将指向 value 容器中元素 1 位置处的 const_iterator 类型迭代器作为该方法的实参,就成功将 10 插入到了 value 容器的指定位置。
那么,是不是给 insert() 方法传递其它类型迭代器就不行呢?当然不是,对于给 const_iterator 类型的迭代器传值,还可以使用 iterator 类型迭代器,但不能使用 const_reverse_iterator 和 reverse_iterator 类型迭代器,这是为什么呢?
实际上,当我们将某一类型的迭代器传递给 insert() 方法中 const_iterator 类型的 position 形参时,即便类型不匹配,编译器也不会立即报错,而是先尝试将其类型转换成 const_iterator 类型,如果转换成功,则程序仍可以正常执行;反之如果转换失败,编译器才会报错。
C++ 中,通常将编译器自行尝试进行类型转换的整个过程称为隐式转换(或者自动类型转换)。
对于 C++ STL 标准库中的这 4 种基础迭代器来说,C++ 编译器的隐式转换仅支持以下 2 种情况:
注意,以上 2 种隐式转换是单向的,即编译器只支持从 iterator 转换为 const_iterator,从 reverse_iterator 转换为 const_reverse_iterator,但不支持逆向转换。
有些读者可能会好奇,既然隐式转换无法做到,还有其他方式可以实现从 const_iterator 到 iterator、从 const_reverse_iterator 到 reverse_iterator 的转换吗?
很多读者可能会想到使用强制类型转换(const_cast)的方式。但可以明确的是,强制类型转换并不适用于迭代器,因为 const_cast 的功能仅是去掉某个类型的 const 修饰符,但 const_iterator 和iterator 是完全不同的 2 个类,同样 const_reverse_iterator 和 reverse_iterator 也是完全不同的 2 个类,它们仅仅是类名有 const 的差别,但并不是 const T 和 T 的关系。
这里给读者推荐一种实现方式,就是使用 advance() 和 distance() 这 2 个函数,其语法格式如下:
//将 const_iterator 转换为 iterator
advance(iter, distance
//将 const_reverse_iterator 转换为 reverse_iterator
advance(iter, distance
其中,citer 为指向某个容器(比如 cont)任意位置的 const_iterator(或者 const_reverse_iterator)类型迭代器,而 iter 通常初始为指向 cont 容器中第一个元素的 iterator(或者 reverse_iterator)类型迭代器。通过套用此格式,最终 iter 会变成一个指向和 citer 一样的 iterator(或者 reverse_iterator)类型迭代器。
注意,在使用 distance() 函数时,必须额外指明 2 个参数为 const 迭代器类型,否则会因为传入的 iter 和 citer 类型不一致导致 distance() 函数编译出错。
该实现方式的本质是,先创建一个迭代器 citer,并将其初始化为指向容器中第一个元素的位置。在此基础上,通过计算和目标迭代器 iter 的距离(调用 distance()),将其移动至和 iter 同一个位置(调用 advance()),由此就可以间接得到一个指向同一位置的 iter 迭代器。
#include
#include
using namespace std;
vectorvalue{ 1,2,3,4,5 };
//定义一个 const_iterator 类型的迭代器,其指向最后一个元素
vector::const_iterator citer = --value.cend();
//初始化一个非 const 迭代器,另其指向
vector::iterator iter = value.begin();
//将 iter 变成和 citer 同样指向的迭代器
advance(iter, distance::const_iterator>(iter, citer));
cout << "*citer = " << *citer << endl;
cout << "*iter = " << *iter << endl;
可以看到,通过使用 advance() 和 distance() 函数的组合格式,最终可以得到一个和 citer 指向相同但类型为 iterator 的迭代器。
注意,此方法的实现效率仍取决于目标容器的迭代器类型,如果是随机访问迭代器,则该方法的执行效率为 O(1);反之,则执行效率为 O(n)。
以下博客部分内容借鉴自:http://c.biancheng.net/stl/。
C++ STL 容器、迭代器、适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120052137 C++ STL deque容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676574
C++ STL vector容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676109
C++ STL list容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676917
C++ STL forward_list容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118687348
C++ STL array 容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118688364
C++ STL pair 类模板(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118714852
C++ STL map容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118741670
C++ STL map emplace()和emplace_hint()(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118771777
C++ STL multimap容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118773021
C++ STL Set容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118918940
C++ STL multiset容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119624779
C++ STL unordered_map容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119689199
C++ STL unordered_set容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119709019
C++ STL unordered_multiset容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119709079
C++ STL stack容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119723782
C++ STL queue容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119746246
C++ STL priority_queue容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119770527
C++ STL reverse_iterator反向迭代器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119814820
C++ STL insert_iterator插入迭代器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119834378
C++ STL stream_iterator流迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119834429
C++ STL streambuf_iterator流缓冲区迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119850048
C++ STL move_iterator移动迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119859888
C++ STL advance()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008250
C++ STL distance()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008300
C++ STL iterator迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008346
C++ STL const_iterator转换为iterator类型迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008324
C++ STL begin()和end()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008459
C++ STL prev()和next()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008481