小众的常量迭代器
这个新特征其实是偶尔在别人的总结中看到的,但觉得确实很有趣,就做个记录:
1. 需求
我们一般在使用STL容器时,下面代码是非常常见的:
int sum = 0;
vector<int> v{1, 2, 3, 4, 5, 6};
vector<int>::iterator it = v.begin();
while(it != v.end()){
sum += *it;
it++;
}
但是,如果我们一旦定义容器为常量,就必须注意迭代器也需要声明为常量:
int sum = 0;
//编译错误:原因是定义的vector是const类型,所以迭代器必须也是const类型
const vector<int> cv{1, 2, 3, 4, 5, 6};
vector<int>::iterator cit = cv.begin();
while(cit != v.end()){
sum += *cit;
cit++;
}
//正确写法:
const vector<int> cv{1, 2, 3, 4, 5, 6};
vector<int>::const_iterator cit = cv.begin();
while(cit != v.end()){
sum += *cit;
cit++;
}
这显然很麻烦,一个简单的方法是直接使用auto来自动推断迭代器类型(想必大家都更倾向于这样,毕竟...有了auto还要啥自行车):
auto ait = cv.begin();
while(ait != cv.end()){
sum += *ait;
ait++;
}
2. 优势
但我们也不难想到存在这样一种情形:数据本身不是const类型,但是从设计的角度来讲有些处理不应该修改该数据。这时也应该要求const类型的迭代器,以避免数据被意外修改。所以,C++11为此提供了cbegin和cend方法。
vector<int> v{1, 2, 3, 4, 5, 6};
auto ait = v.cbegin();
while(ait != v.cend()){
sum += *ait;
*ait = sum; //编译错误
ait++;
}
cbegin()/cend()决定了返回的迭代器类型为const。这时即使vector的类型不是const,也可以防止对该数据的误操作。