将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?

Posted

技术标签:

【中文标题】将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?【英文标题】: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 类型? (它编译)。

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

【问题讨论】:

【参考方案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

【讨论】:

+1 请参阅open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3585.pdf 以获取解决此问题的建议。搜索“空迭代器”。【参考方案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 的内存块)

以上是关于将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将空列表传递给函数以收集结果

如何迭代地将参数传递给 R 函数

为啥 C++ 共享指针的行为不像迭代器的标准指针?

如何简洁地将一个数组的范围分配给另一个数组的范围?

在 React 中将状态变量和方法传递给子组件的更简洁的方法?

带有int迭代器的Python循环[重复]