阅读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 元素的“指针”吗?
感谢。
答案 0 :(得分:1)
是的,迭代器就像指针一样。 std::string::iterator
甚至可以是char *
的别名,但通常不是。{/ p>
通常,迭代器提供指针功能的子集。哪个子集取决于迭代器。您的书可能涵盖了这一点,但所有迭代器都可以取消引用(*
,但从不引用&
操作)并递增(++
),然后有些还提供了--
,有些还添加了+
和-
。
在这种情况下,函数似乎假设您只是在不修改字符串的情况下查询迭代器的值。因为用于字符串存储的分配块可能随着字符串的增长而改变,所以字符串中的迭代器(如指针)可能无效。这就是std::string
成员函数如string::find
返回索引号而不是迭代器的原因。
索引向量可能是更好的设计选择,但这对于一个例子来说已经足够了。
答案 1 :(得分:1)
我对find_all()返回的向量包含的内容感到有些困惑。它本质上是指向它上面创建的字符串m的元素的“指针”吗?
晴;迭代器不是(必然)指针,它们有点是指针概念的概括。它们用于指向存储在容器内的特定对象(在本例中是字符串中的字符),您可以使用它们在字符串的元素之间移动(通过常用的算术运算符 - 当它们受支持时)并且您“取消引用“他们用*
获取对尖头对象的引用。
请注意,根据容器的不同,它们的实现方式不同,并提供不同的功能;例如,std::list
的迭代器将允许++
,--
和*,但不会移动到任意位置,并且单链接列表的迭代器甚至不支持--
,而通常对类似数组的数据结构(如vector
或string
)的迭代器将允许完全自由移动。
为了引用类似数组结构中的元素,通常只存储索引,因为它们的存储和使用都很便宜;对于其他结构,相反,存储迭代器可能更方便。
例如,就在昨天,我有一些代码走了unordered_set<string, int>
(=一个哈希表,将一些单词映射到它们的出现位置),以“注意”一些(字符串,整数)对使用它们后面。
这里存储矢量索引的等价物就是存储哈希表的密钥,但是(1)它们是字符串(因此分配和处理成本相当高),以及(2)使用它们到达相应的对象I不得不稍后再做一个哈希表查找。相反,将迭代器存储在向量中可以保证存储字符串没有麻烦(迭代器的处理成本很低)并且不需要再次执行查找。