8

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

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

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

我想写这个:

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

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

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

4

2 回答 2

7

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

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
于 2013-03-28T22:39:13.013 回答
1

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

由于所有指针都是有效的迭代器,因此您应该能够将其static_cast<int*>(NULL)用作两个参数。(或vector<int>::iterator())。

于 2013-03-28T22:07:57.600 回答