1

最近我在考虑如果迭代器隐式转换为 bool 会很好,这样你就可以做到

auto it = find(begin(x),end(x), 42);
if (it)  //not it!=x.end();
{
}

但考虑到它,我意识到这意味着要么it必须设置为“NULL”,所以如果你想用它做某事你不能直接使用它(你必须使用x.end())或者你可以使用它但是迭代器的大小必须更大(如果它指向的是存储,则存储它 .end())。所以我的问题是:

  1. 我的示例中的语法是否可以在不破坏当前代码且不增加迭代器大小的情况下实现?
  2. 隐式转换为 bool 会导致一些问题吗?
4

4 回答 4

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). 在第二种情况下,根本没有容器。

请注意,许多容器的迭代器的有效实现只包含一个指针,因此任何其他状态都会增加迭代器的大小。

关于到任何类型的转换or bool,它们确实会引起很多问题,但是在 C++11 中可以通过explicit转换来规避它们,或者在 C++03 中使用安全布尔成语。

您可能对不同的概念更感兴趣:范围。范围有多种方法,因此尚不清楚确切的语义应该是什么。想到的前两个是 Boost.Iterator 和我最近阅读的 Alexandrescu 的一篇文章On Iteration

于 2012-10-05T16:10:07.010 回答
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 循环是朝着这一目标迈出的第一步)。

于 2012-10-05T16:16:39.140 回答
2

好吧,您可能不想要隐式转换,但是需要两个单独的对象来确定迭代何时完成显然是一个设计错误。这不是因为ifor for(尽管使用单个迭代器也会使这些更清晰);这真的是因为它使功能分解和过滤迭代器变得非常困难,如果不是不可能的话。

从根本上说,与迭代器相比,STL 迭代器更接近智能指针。有时这样的指针是合适的,但它们并不是迭代器的良好替代品。

于 2012-10-05T17:04:39.967 回答
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, ' ');
于 2012-10-05T16:13:41.247 回答