0

在阅读 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的元素的“指针”吗?

谢谢。

4

2 回答 2

1

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

大多; 迭代器不是(必然)指针,它们在某种程度上是指针概念的概括。它们用于指向存储在容器中的特定对象(在这种情况下,是字符串中的字符),您可以使用它们在字符串的元素之间移动(通过通常的算术运算符 - 当它们被支持时)并且您“取消引用" 他们*用来获取指向对象的引用。

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

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

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

在这里存储向量索引的等价物是存储哈希表的键,但是(1)它们是字符串(因此它们的分配和处理成本适中),以及(2)使用它们来访问我必须做的相应对象稍后进行另一个哈希表查找。取而代之的是,将迭代器存储在向量中保证了存储字符串不会有任何麻烦(迭代器的处理成本很低)并且无需再次执行查找。

于 2013-11-03T01:23:00.447 回答
1

是的,迭代器就像指针。std::string::iterator甚至可以是 的别名char *,尽管通常不是。

通常,迭代器提供指针功能的子集。哪个子集取决于迭代器。您的书可能涵盖了这一点,但是所有迭代器都可以被取消引用(*,但从来没有引用&操作)和递增(++),然后一些额外提供--,一些添加+-在此之上。

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

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

于 2013-11-03T01:22:37.883 回答