STL Iterator - Range Access (Part II)

Range Access (Since C++11)

我们在第一部分提到,STL 迭代器相当于泛化的指针,它的作用就是为不同数据结构提供统一的遍历和访问接口。Range access 就是一组统一操作容器的标准库函数。这些函数可以提供对数据范围的起始位置、结束位置、大小和判断空信息的访问。其中很多函数我们已经见过很多遍了。

begin() / end()

这两个函数用于返回容器的起始和结束迭代器(或者指针)。

range-begin-end.svg

#include <vector>

int main(){
	int custom_arr[] = {1, 2, 3};
	std::vector<int> vec = {4, 5, 6};
	auto arr_begin = std::begin(custom_arr); // return int*
	// auto arr_begin = custom_arr.begin(); // illegal
	*arr_begin = 10;
	auto vec_begin = std::begin(vec);  // return vector<int>::iterator
	auto vec_begin1 = vec.begin(); // okay for STL containers
	*vec_begin = 10;
	return 0;
}

如果对象是标准库容器,你就可以写成下面那种形式。

cbegin() / cend()

这两个函数用于返回容器的常量迭代器(或指针)。也就是说,所返回的迭代器只能读,不能写。

#include <vector>

int main(){
	int custom_arr[] = {1, 2, 3};
	std::vector<int> vec = {4, 5, 6};
	auto arr_begin = std::cbegin(custom_arr);
	// *arr_begin = 10; // illegal
	auto vec_begin = std::cbegin(vec);
	// *vec_begin = 10; // illegal
	return 0;
}

rbegin() / rend()

这两个 range access 函数很有意思,它返回的是反向的迭代器,用途是逆序遍历。它的作用如下图所示:

range-rbegin-rend.svg
rbegin()end() 并不相同,它们并不能比较,一个是正向迭代器,一个是反向迭代器。你可以用 base() 方法 (如 rbegin().base()) 将反向迭代器转换成正向迭代器。

#include <vector>
#include <iostream>

int main(){
	std::vector<int> vec = {4, 5, 6};
	auto vec_rbegin = std::rbegin(vec);
	for(; vec_rbegin != vec.rend(); ++vec_rbegin){
		std::cout << *vec_rbegin << " ";
	}
	//auto vec_end = std::end(vec);
	//if(vec_rbegin == vec_end){
	//	std::cout << "They are the same..." << std::endl;
	//}
	return 0;
}

// Prints 6 5 4

crbegin() / crend()

size()

返回容器或数组的元素个数。

empty()

检查容器是否为空。即元素个数是否为 0 。

data()

返回指向容器或数组底层数据存储的指针。常常用于与 C 接口交互。