需要澄清C ++ std :: iterator

时间:2013-11-03 01:11:36

标签: c++ iterator

阅读C ++书籍我在使用迭代器时遇到了以下示例:

vector<string::iterator> find_all(string& s, char c)
{
    vector<string::iterator> res;
    for(auto p = s.begin(); p != s.end(); ++p)
        if(*p == c)
            res.push_back(p);
    return res;
}

void test()
{
    string m {"Mary had a little lamb"};
    for(auto p : find_all(m, 'a'))
        if(*p != 'a')
            cerr << "a bug!\n";
}

我对 find_all()返回的向量包含的内容感到有些困惑。它本质上是指向它上面创建的字符串 m 元素的“指针”吗?

感谢。

2 个答案:

答案 0 :(得分:1)

是的,迭代器就像指针一样。 std::string::iterator甚至可以是char *的别名,但通常不是。{/ p>

通常,迭代器提供指针功能的子集。哪个子集取决于迭代器。您的书可能涵盖了这一点,但所有迭代器都可以取消引用(*,但从不引用&操作)并递增(++),然后有些还提供了--,有些还添加了+-

在这种情况下,函数似乎假设您只是在不修改字符串的情况下查询迭代器的值。因为用于字符串存储的分配块可能随着字符串的增长而改变,所以字符串中的迭代器(如指针)可能无效。这就是std::string成员函数如string::find返回索引号而不是迭代器的原因。

索引向量可能是更好的设计选择,但这对于一个例子来说已经足够了。

答案 1 :(得分:1)

  

我对find_all()返回的向量包含的内容感到有些困惑。它本质上是指向它上面创建的字符串m的元素的“指针”吗?

晴;迭代器不是(必然)指针,它们有点是指针概念的概括。它们用于指向存储在容器内的特定对象(在本例中是字符串中的字符),您可以使用它们在字符串的元素之间移动(通过常用的算术运算符 - 当它们受支持时)并且您“取消引用“他们用*获取对尖头对象的引用。

请注意,根据容器的不同,它们的实现方式不同,并提供不同的功能;例如,std::list的迭代器将允许++--和*,但不会移动到任意位置,并且单链接列表的迭代器甚至不支持--,而通常对类似数组的数据结构(如vectorstring)的迭代器将允许完全自由移动。

为了引用类似数组结构中的元素,通常只存储索引,因为它们的存储和使用都很便宜;对于其他结构,相反,存储迭代器可能更方便。

例如,就在昨天,我有一些代码走了unordered_set<string, int>(=一个哈希表,将一些单词映射到它们的出现位置),以“注意”一些(字符串,整数)对使用它们后面。

这里存储矢量索引的等价物就是存储哈希表的密钥,但是(1)它们是字符串(因此分配和处理成本相当高),以及(2)使用它们到达相应的对象I不得不稍后再做一个哈希表查找。相反,将迭代器存储在向量中可以保证存储字符串没有麻烦(迭代器的处理成本很低)并且不需要再次执行查找。