注意,上面提到的 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 <iostream> #include <vector> using namespace std; int main() { vector<int>value{ 1,2,3,4,5 }; //定义一个 const_iterator 类型的迭代器 vector<int>::const_iterator citer = value.cbegin(); value.insert(citer, 10); for (auto iter = value.begin(); iter != value.end(); ++iter) { cout << *iter << " "; } return 0; }
程序执行结果为:
10 1 2 3 4 5
显然通过调用 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 种情况:
- 将 iterator 类型的迭代器隐式转换为 const_iterator 类型的迭代器;
- 将 reverse_iterator 类型的迭代器隐式转换为 const_reverse_iterator 类型的迭代器。
注意,以上 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<cont<T>::const_iterator>(iter,citer));
//将 const_reverse_iterator 转换为 reverse_iterator
advance(iter, distance<cont<T>::const_reverse_iterator>(iter,citer));
其中,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 <iostream> #include <vector> using namespace std; int main() { vector<int>value{ 1,2,3,4,5 }; //定义一个 const_iterator 类型的迭代器,其指向最后一个元素 vector<int>::const_iterator citer = --value.cend(); //初始化一个非 const 迭代器,另其指向 vector<int>::iterator iter = value.begin(); //将 iter 变成和 citer 同样指向的迭代器 advance(iter, distance<vector<int>::const_iterator>(iter, citer)); cout <<"*citer = " << *citer << endl; cout << "*iter = " << *iter << endl; return 0; }
程序执行结果为:
*citer = 5
*iter = 5
可以看到,通过使用 advance() 和 distance() 函数的组合格式,最终可以得到一个和 citer 指向相同但类型为 iterator 的迭代器。
注意,此方法的实现效率仍取决于目标容器的迭代器类型,如果是随机访问迭代器,则该方法的执行效率为 O(1);反之,则执行效率为 O(n)。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/23740.html