【问题标题】:What is a clean/concise way to pass empty range to a function taking a pair of iterators?将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是什么?
【发布时间】:2013-03-28 22:05:55
【问题描述】:

我有一个带有一对迭代器的函数。我想提供一个无参数版本的函数,它的行为就好像它被传递了一个空范围。

具体来说,假设第一个函数是:

void f(vector<int>::iterator b, vector<int>::iterator e) { // impl. }

我想写这个:

void f() { f({}, {}); }

这里的初始化是否正确,{}、{} 应该是两个默认构造的 vector::iterator 类型? (它编译)。

我是否必须构造一个容器来获得一对比较相等的迭代器?

【问题讨论】:

    标签: c++ stl c++11


    【解决方案1】:

    据我了解,这通常不能以符合标准的方式完成。

    24.2.1/5

    迭代器也可以有不相关的奇异值 任何序列。 [ 例子:声明一个未初始化的之后 指针 x(与 int* x; 一样),必须始终假定 x 具有 指针的奇异值。 — 结束示例] 大多数结果 奇异值的表达式未定义;唯一的例外是 销毁持有奇异值的迭代器,分配 持有奇异值的迭代器的非奇异值,并且, 对于满足DefaultConstructible 要求的迭代器, 使用值初始化的迭代器作为复制或移动的源 手术。 [注意:默认情况下不提供此保证 初始化,尽管区别只对具有 微不足道的默认构造函数,例如持有的指针或聚合 指针。 — 尾注] 在这些情况下,奇异值是 以与任何其他值相同的方式覆盖。可取消引用的值 总是非单数的。

    默认/值初始化显然与任何序列无关,因此迭代器是单数的。 比较两个奇异的迭代器是未定义的行为。

    std::vector<int>::iterator i;
    std::vector<int>::iterator j = i; // UB, assignment of a non-a singular value
                                      // If you pass `i` to a function, a copy is done
                                      // which also results in UB (as in Andy's answer).
    

    下一次尝试,使用值初始化

    std::vector<int>::iterator i{};
    std::vector<int>::iterator j = i; // ok, i is value-initialized
    i == j; // undefined, comparison is not explicitly non-undefined behavour
    i == i; // undefined, comparison is not explicitly non-undefined behavour 
    

    由于我们没有关于vector&lt;int&gt;::iterator 的更多信息,因此您的方法是错误的。

    您可以做的是将您的f 更改为模板并使用指针:

    template <typename Iter>
    void f(Iter b, Iter e);
    
    int *p; f(p, p); // ok, defined for pointers
    

    【讨论】:

    【解决方案2】:

    相信迭代器的默认构造函数总是等价于end。也就是说,如果您将相同的迭代器传递给函数,那么根据定义,这也是一个空范围。

    由于所有指针都是有效的迭代器,您应该能够使用static_cast&lt;int*&gt;(NULL) 作为两个参数。 (或vector&lt;int&gt;::iterator())。

    【讨论】:

    • 这不是真的。这取决于迭代器的类型,在大多数情况下,默认构造的迭代器是 singular 并且不同于 end()。关于指针,在某些实现中std::vector&lt;int&gt;::iteratorint*,但您也不能依赖它,因为在您的特定库中(并且取决于编译标志)它可能会有所不同。
    • 啊,好的。感谢您的澄清!我想在最初阅读它时,我一直在考虑将模板化迭代器作为输入的 STL 风格的函数。说static_cast&lt;int*&gt;(NULL) 是一个有效的迭代器是真的吗(即使与vector&lt;int&gt;::iterator 的类型不同)?
    • 是的,迭代器对指针的行为进行建模,并且指针满足所有随机访问迭代器的要求。这很好,因为它可以在原始内存上使用标准算法(无论是数组还是分配有new[]/malloc 的内存块)
    猜你喜欢
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 2012-03-13
    • 2021-08-21
    • 2022-12-10
    • 1970-01-01
    相关资源
    最近更新 更多