我目前正在"现代化"我的玩具编译器代码使用尽可能多的C ++ 11功能来学习如何编写现代C ++。在查看我的代码,搜索现代化的东西时,我发现了这个构造:
for (size_t i = 0; i < _vector.size(); i++) {
for (size_t j = 0; j < _vector[i].length(); j++) {
_vector是一个std::vector<std::string>
,包含需要编译的文件的源代码。向量中的每个std::string
都是需要编译的一行代码。在编译之前,编译器会检查要编译的代码是否有任何语法错误,此检查的第一步是查找缺少的分号。我这样做是通过逐个查看每个字符并检查所述字符是否是分号。如果是,我通过构建一种迷你语法树来检查是否需要分号,从而确定是否有必要。我目前使用_vector[i][j]
访问每个字符,这非常让人想起ANSI-C(这是你访问char *数组中每个字符的方式),我想用迭代器替换它。据我所知,Iterator是一个类似指针的构造,它指向容器/序列/中的元素。应用指针类比我推断出std::vector<std::string>::iterator
指向向量中的字符串,因此理论std::vector<std::string>::iterator::iterator
将指向字符串对象中的单个字符。但是因为在STL中没有这样的东西,指针类比在这里没有多大用处。所以我的问题是:如何访问std::vector<std::string>::iterator
中的每个角色?
答案 0 :(得分:5)
如果您可以访问完整的C ++ 11支持,为什么还要使用显式迭代器类型呢?这就是auto
的来源:
std::vector<std::string> sv;
//fill vector...
for(const auto& s : sv)
{
for(const auto& c : s)
{
//'c' represents current character
}
}
我们在这里使用range-base for loop。在第一个循环中,s
是一个const引用 (*) 到来自vector的当前字符串。由于std::string支持迭代语义,我们也可以使用for
迭代它。 c
是对字符串(s
)中当前字符的const引用。
现场演示: click 。
(*) 由于您的循环似乎是只读的,因此应使用const引用。如果您要执行任何修改,只需将其从const auto&
更改为auto&
。
答案 1 :(得分:2)
iterator
的行为类似于指针。因此,在您的情况下,您可以取消引用第一个迭代器以获取string
并使用std::string::iterator
来访问每个字符。
另一种方法是使用operator->()
直接获取std::string::iterator
,例如
for (std::vector<std::string>::iterator i = _vector.begin(); i != _vector.end(); ++i) {
for (std::string::iterator j = i->begin(); j != i->end(); ++j) {
/* ... */
}
}
使用C ++ 11,您可以将其简化为
for (auto i = _vector.begin(); i != _vector.end(); ++i) {
for (auto j = i->begin(); j != i->end(); ++j) {
/* ... */
}
}
正如@LightnessRacesinOrbit提到并且@MateuszGrzejek已经显示,下一步将转移到Range-based for loop。从第一个begin()
到最后一个end()
元素迭代的循环
for (auto i = _vector.begin(); i != _vector.end(); ++i) {
// Do something with string (*i)
可以写成
for (auto &s : _vector) {
// Do something with string (s)
或者,如果您不修改字符串,请将其设为const
for (const auto &s : _vector) {
// Do something with string (s)