将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?
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<int>::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<int*>(NULL)
作为两个参数。 (或vector<int>::iterator()
)。
【讨论】:
这不是真的。这取决于迭代器的类型,在大多数情况下,默认构造的迭代器是 singular 并且不同于end()
。关于指针,在某些实现中std::vector<int>::iterator
是int*
,但您也不能依赖它,因为在您的特定库中(并且取决于编译标志)它可能会有所不同。
啊,好的。感谢您的澄清!我想在最初阅读它时,我一直在考虑将模板化迭代器作为输入的 STL 风格的函数。说static_cast<int*>(NULL)
是一个有效的迭代器是真的吗(即使与vector<int>::iterator
的类型不同)?
是的,迭代器对指针的行为进行建模,并且指针满足所有随机访问迭代器的要求。这很好,因为它可以在原始内存上使用标准算法(无论是数组还是分配有new[]
/malloc
的内存块)以上是关于将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章