STL算法和const迭代器

5
今天我编写了一个小的谓词函数,用于在容器中查找匹配的符号。
但是我面临一个问题:我想将这个谓词函数用于类的const方法内,在该类的成员容器中搜索时使用std :: find_if调用。
但是我刚刚注意到,既不是std :: find也不是std :: find_if能够在const_iterator上操作!
我在一些C ++参考资料上检查了一下,似乎没有版本的std :: find或std :: find_if接受/返回const_iterator。我就是无法理解为什么,因为据我所见,这些算法不可能修改迭代器引用的对象。
以下是SGI实现中std :: find的文档说明:
返回范围[first,last)中第一个满足*i==value的迭代器i。 如果不存在这样的迭代器,则返回last。

你实际上遇到了什么错误?你能否也发布一些示例代码?谢谢。 - Binary Worrier
2
实际上,你只是误读了文档,请参见下面 Pavel 的回答。如果你测试了,你会发现它绝对有效。 - Matthieu M.
你的问题暗示着你有一些代码无法正常工作,特别是“但我面临一个问题”,而实际上你只是在自言自语。我对这个问题进行了负评,因为如果你尝试过,你就会发现它可以工作。 - Binary Worrier
5个回答

16

std::findstd::find_if可以在给定容器的*::const_iterator上进行操作。你是不是看到这些函数的签名并且误解了它们呢?

template <class InputIterator, class Type>
InputIterator find(InputIterator first, InputIterator last, const Type& val);
请注意,这里的InputIterator只是模板类型参数的名称,并且任何const_iterator都可以满足其要求。
或者,也许你正在混淆const_iterator(即引用常量值的迭代器)和一个const迭代器(即迭代器本身是const)?

哦,猜我来晚了,我刚刚看了几十份文档,每次都只读我想要的,而不是写的内容 x( 感谢您的耐心等待。 - NewbiZ

5

std::findstd::find_if都使用迭代器类型作为模板参数,因此它们肯定可以操作const_iterators。举个快速示例:

#include <vector>
#include <algorithm>
#include <iostream>
int main() { 
    std::vector<int> x;

    std::fill_n(std::back_inserter(x), 20, 2);
    x.push_back(3);

    std::vector<int>::const_iterator b = x.begin();
    std::vector<int>::const_iterator e = x.end();

    std::vector<int>::const_iterator p = std::find(b, e, 3);

    std::cout << *p << " found at position: " << std::distance(b, p) << "\n";
    return 0;
}

任何正常工作的C++编译器都应该接受这个,且产生类似以下结果:

3被找到,位置在:20


2
如果你和我一样是来这里的原因:
error: no matching function for call to ‘find(std::vector<int>::const_iterator, std::vector<int>::const_iterator, int)’

这与const_iterator无关。你可能只是忘记了#include :-)

1

我刚遇到了同样的问题。我的一个成员函数在成员向量上调用了find_if,当我尝试将该成员函数设置为const时,编译器给出了错误提示。原来是因为我将find_if的返回值赋给了iterator而不是const_iterator。这导致编译器假定find_if的参数也必须是iterator而不是const_iterator,而这无法从const成员向量中获取。


0

我刚刚遇到了这段代码的问题:

std::string str;
std::string::const_iterator start = str.begin();
std::string::const_iterator match = std::find(start, str.end(), 'x');

错误是“没有匹配的std::find重载”。

我需要的修复方法是使用cend()。令人困惑的是cbegin()不是必需的,我不确定为什么这种转换是可以的(隐式地),而end()作为函数参数却不行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接