最近我在考虑如果迭代器隐式转换为bool你会怎么做
auto it = find(begin(x),end(x), 42);
if (it) //not it!=x.end();
{
}
但是考虑到这一点我意识到这意味着要么it
必须设置为“NULL”,所以如果你想用它做某事你就不能直接使用它(你会有使用x.end()
)或者你可以使用它,但它的大小必须更大(如果指的是.end()
则存储)。
所以我的问题是:
答案 0 :(得分:3)
您正在假设迭代器是一种访问容器的方式。它们允许您这样做,但它们还允许更多明显不符合您预期操作的内容:
auto it = std::find(std::begin(x), std::next(std::begin(x),10), 42 );
// Is 42 among the first 10 elements of 'x'?
auto it = std::find(std::istream_iterator<int>(std::cout),
std::istream_iterator<int>(), 42 );
// Is 42 one of the numbers from standard input?
在第一种情况下,迭代器确实引用了一个容器,但是你找到的范围并没有包含整个容器,因此it
无法针对end(x)
进行测试}。在第二种情况下,根本没有容器。
请注意,许多容器的迭代器的有效实现仅包含指针,因此任何其他状态都会增加迭代器的大小。
关于任何类型或bool
的转换,它们确实会导致许多问题,但可以通过explicit
转换在C ++ 11中规避这些问题,或者在C ++ 03中使用 safe-bool 成语。
你可能对另一个概念更感兴趣:范围。范围有多种方法,因此不太清楚精确语义应该是什么。我想到的前两个是Boost.Iterator和我最近阅读的一篇名为On Iteration的Alexandrescu的文章。
答案 1 :(得分:2)
这不起作用的两个原因:
首先,可以使用原始指针作为迭代器(通常是数组):
int data[] = { 50, 42, 37, 5 };
auto it = find(begin(data), end(data), 42);
其次,您不必将容器的实际末尾传递给find
;例如在句点之前找到第一个空格字符:
auto sentence = "Hello, world.";
auto it1 = find(begin(sentence), end(sentence), '.');
auto it2 = find(begin(sentence), it1, ' ');
答案 2 :(得分:2)
使用单个迭代器可以做的很少。 对迭代器定义了由元素组成的序列;第一个迭代器指向第一个元素,第二个迭代器指向一个超过最后一个元素的末尾。通常,第一个迭代器无法知道它何时递增以匹配第二个迭代器。算法可以做到这一点,因为它们都有迭代器,可以判断工作何时完成。例如:
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
// copy the contents of the vector:
std::copy(somewhere, vec.begin(), vec.end());
// copy the first two elements of the vector:
std::copy(somewhere, vec.begin(), vec.begin() + 2);
在两次复制调用中,vec.begin()
都是相同的迭代器;算法做了不同的事情,因为它得到了第二个迭代器,告诉它什么时候停止。
当然,可以设计一种不同类型的迭代器,它包含序列的开头和结尾(就像Java那样),但这不是C ++迭代器的设计方式。有关标准化“范围”概念的讨论,该范围包含两个迭代器(新的基于范围的for循环是向前迈出的第一步)。
答案 3 :(得分:2)
好吧,您可能不希望进行隐式转换,但需要两个
单独的对象来确定何时完成迭代显然是一种设计
错误。这不是因为if
或for
(尽管如此)
使用单个迭代器也可以使这些更清晰;)是真的
因为它使功能分解和过滤迭代器
即使不是不可能,也会非常困难。
从根本上说,STL迭代器比它们更接近智能指针 到迭代器。有时候这样的指针是合适的,但是 它们不是迭代器的好替代品。