【问题标题】:Any guarantees with vector<bool> iterators?vector<bool> 迭代器的任何保证?
【发布时间】:2016-12-27 14:41:21
【问题描述】:

cppreference 表示vector&lt;bool&gt; 特化的迭代器是实现定义的,并且许多不支持像ForwardIterator 这样的特征(因此RandomAccessIterator)。

cplusplus加了一个神秘的“最”:

容器使用的指针和迭代器类型不是 既不是指针也不是一致的迭代器,尽管它们 应模拟他们的大部分预期行为。

我无权访问官方规范。 vector&lt;bool&gt; 迭代器是否有任何迭代器行为保证?

更具体地说,如何编写符合标准的代码来在vector&lt;bool&gt; 中间插入一个项目?以下适用于我尝试过的几个编译器:

std::vector<bool> v(4);
int k = 2;
v.insert(v.begin() + k, true);

会一直这样吗?

【问题讨论】:

  • 一句话:不! std::vector&lt;bool&gt; 专业化被打破了,
  • 一句话:是的!除非你赞同(太普遍的)观念,即如果它不完美,那就没用了。工程就是让事情发挥作用,而不是抱怨它们不是你想要的。
  • @PeteBecker:std::sort 将在来自vector&lt;bool&gt;. 的迭代器上工作如果该问题的答案是“我不知道”(确实如此),那么事情就无法正常工作。是的,用户 可以编写从vector&lt;bool&gt; 获取迭代器的代码。但不能保证任何标准库算法都可以使用它们。
  • @NicolBolas - C++14 [vector.bool]/2 似乎不同意你的观点。
  • @PeteBecker:C++14 [forward.iterators]/1 同意我的观点。请参阅下面的答案。

标签: c++ vector iterator


【解决方案1】:

C++14 [vector.bool]/2:

除非下面描述,所有操作都具有相同的要求和 语义作为主要vector 模板,除了操作 处理 bool 值类型映射到容器中的位值 存储和allocator_traits::construct (20.7.8.2) 不用于 构造这些值。

【讨论】:

  • 我也找到了this(有点明显)。
【解决方案2】:

vector&lt;bool&gt; 的迭代器的根本问题是它们不是 ForwardIterators。 C++14 [forward.iterators]/1 要求 ForwardIterators 的 reference 类型为 T&amp;const T&amp;,视情况而定。

任何在Ts 范围内采用前向迭代器的函数都可以这样做:

T &t = *it;
t = //Some value.

但是,vector&lt;bool&gt;reference 类型不是bool&amp;;他们是proxy object that is convertible to and assignable from a bool. 他们表现得像bool,但他们不是bool。因此,此代码是非法的:

bool &b = *it;

它将尝试获取对从代理对象创建的临时对象的左值引用。这是不允许的。

因此,您不能在任何采用 ForwardIterators 或更高版本的函数中使用 vector&lt;bool&gt; 的迭代器。

但是,您的代码不一定要关心这一点。只要您控制将这些 vector&lt;bool&gt; 迭代器传递给的代码,并且您不做任何违反它们行为方式的事情,那么您就可以了。

就它们的接口而言,它们的行为类似于 RandomAccessIterators,除非它们不这样做(见上文)。所以你可以用具有恒定时间复杂度的整数等来抵消它们。

vector&lt;bool&gt; 没问题,只要您不将其视为包含 bools 的 vector。您的代码可以工作,因为它使用vector&lt;bool&gt; 自己的接口,它显然接受了。

如果您将一对 vector&lt;bool&gt; 迭代器传递给 std::sort,它将不起作用。

【讨论】:

  • 您在哪里找到std::sort 使用T &amp;t = *it; 的要求?由于这显然违反了 [vector.bool]/2 中的要求,因此是不允许的。通常的做法是做*it = //Some value,这是代理迭代器的预期使用方式。
  • @PeteBecker: "你在哪里找到要求 std::sort 使用 T &t = *it;?" 我没有。但是,因为它需要 RandomAccessIterators,所以允许sort 这样做,因为这是 RandomAccessIterators 上允许的操作。不,它不会违反 [vector.bool]/2;请注意,vector&lt;bool&gt;::iterator::reference 的行为是“除非下面描述”部分的一部分。
  • 简单地尝试一下就可以得到一些模糊的支持证据不是很容易吗?
  • @NicolBolas - 嗯,标准的语言部分使用与库部分完全不同的形式,原因很明显:它必须说明T&amp; 的含义。请记住,这些更改的目的是使代理迭代器工作;也许如果你斜视得恰到好处,你可能会想出一种解释,使这种努力完全失败,但这充其量是不慷慨的。
  • @Justin:这是说“除非下面描述,所有操作都具有与主向量模板相同的要求和语义”的部分。迭代器关于随机访问的行为没有“在下面描述”,所以它“就像一个随机访问迭代器”。
猜你喜欢
  • 1970-01-01
  • 2016-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
相关资源
最近更新 更多