【问题标题】:Is it well-defined to compare with a value-initialized iterator?与值初始化的迭代器进行比较是否定义明确?
【发布时间】:2014-12-02 05:26:26
【问题描述】:

以下程序是否调用未定义的行为?

#include <iostream>
#include <iterator>

int main(int argc, char* argv[])
{
    for (auto it = std::istream_iterator<std::string>(std::cin);
         it != std::istream_iterator<std::string>();
         ++it)
    {
        std::cout << *it << " ";
    }

    return 0;
}

这个4 year old question 说他们无法比较:

迭代器也可以有不相关的奇异值 任何容器。 【例子:声明一个未初始化的之后 指针 x(与 int* x; 一样),必须始终假定 x 具有 指针的奇异值。 ] 大多数表达式的结果是 未定义奇异值;唯一的例外是分配 将非奇异值转换为包含奇异值的迭代器。

但是对于 C++14 标准的另一个答案:

然而,值初始化的迭代器可以被比较并且应该被比较 等于其他相同类型的值初始化迭代器。

【问题讨论】:

  • 不习惯以这种方式使用迭代器,循环何时结束(或您希望结束)?
  • 这个循环确实是定义良好的,它就像任何其他迭代器循环一样,你有它的开始并循环到它的结束。在调用中使用像这样的输入流迭代器也很常见。 std::copy 将流中的所有值获取到一个向量中,例如,参见 this std::istream_iterator reference page 中的示例代码。
  • 我担心你正在混合比较迭代器和取消引用迭代器的比较值,其中取消引用 end() 是未定义的。

标签: c++ c++11


【解决方案1】:

您将两个不同的问题混为一谈。

istream_iterator 是输入迭代器,而不是前向迭代器,因此您引用的 C++14 更改根本不适用于它。您可以以这种方式比较istream_iterators,因为它们被明确指定为允许此类比较。标准说(§24.6.1 [istream.iterator])

没有参数的构造函数istream_iterator()总是 构造一个流尾输入迭代器对象,它是唯一的 用于结束条件的合法迭代器。 [...]

两个流尾迭代器总是相等的。流的结束 迭代器不等于非流结束迭代器。二 非流结束迭代器在构造时是相等的 同一个流。

对于前向迭代器(也包括双向和随机访问的),一般来说,值初始化的迭代器在C++14 中可以相互比较。如果您的标准库实现了它,那么您可以比较两个值初始化的迭代器。这允许您创建一个没有基础容器的空范围。但是,仍然不允许将非奇异迭代器与值初始化的迭代器进行比较。即使在 C++14 中,以下代码也具有未定义的行为:

std::list<int> l;

if(l.begin() == std::list<int>::iterator())
    foo();
else 
    bar();

【讨论】:

    猜你喜欢
    • 2016-05-25
    • 2020-09-27
    • 1970-01-01
    • 2020-07-20
    • 2020-05-09
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多