operator | = on std :: vector <bool> </bool>

时间:2015-03-05 16:35:23

标签: c++ bit-fields boolean-operations

以下代码无法编译

#include <vector>
int main()
{
  std::vector<bool> enable(10);
  enable[0] |= true;
  return 0;
}

给出错误

no match for ‘operator|=’ (operand types are ‘std::vector<bool>::reference {aka std::_Bit_reference}’ and ‘bool’)

在我的现实代码中,我有一个字段,其中包含我想要|=的值以及函数的结果。

有一种简单的方法可以表达相同的想法,但是有没有充分的理由让这样的操作员无法使用?

4 个答案:

答案 0 :(得分:4)

主要原因是std::vector<bool>很特殊,其规范特别允许实现最小化内存使用。

对于bool以外的任何向量,引用类型实际上可以是真正的引用(即std::vector<int>::reference实际上可以是int &) - 通常直接引用向量的元素本身。因此,引用类型支持底层类型可以执行的所有操作是有意义的。这是有效的,因为vector<int>在内部有效地管理了int的连续数组。除bool以外的所有类型都是如此。

但是,为了最大程度地减少内存使用量,std::vector<bool>可能(实际上可能不会)内部使用bool的实际数组。相反,它可能使用一些打包数据结构,例如内部unsigned char的数组,其中每个unsigned char是包含8位的位域。因此,长度为800的vector<bool>实际上将管理100无符号字符的数组,并且它消耗的内存将是100字节(假设没有过度分配)。如果vector<bool>实际包含800 bool数组,则其内存使用量至少为800个字节(因为sizeof(bool)必须至少为{{1}根据定义)。

为了允许1的实施者进行此类内存优化,vector<bool>的返回类型(即vector<bool>::operator[])不能简单地为std::vector<bool>::reference。在内部,它可能包含对基础类型的引用(例如bool &)和跟踪它实际影响的位的信息。这会使所有运算符unsigned char运算符(=+=-=等)对基础类型进行稍微昂贵的操作(例如bit fingdling)。

|=的设计者将面临

之间的选择
  1. 指定std::vector<bool>支持所有 op std::vector<bool>::reference并听取关于运行时效率低下的持续抱怨 使用这些运算符的程序员

  2. 不要支持那些认为这些事情没事的程序员的=和现场投诉(&#34;更干净的代码&#34;等),即使它们效率低下也是如此。

  3. =的设计人员似乎选择了选项2.结果是std::vector<bool>支持的唯一赋值运算符是库存标准std::vector<bool>::reference(操作数类型为{{} 1}},或类型operator=()),而不是任何操作reference。这种选择的优点是,如果尝试做一些在实践中实际上是不好选择的事情,程序员会遇到编译错误。

    毕竟,虽然bool支持使用它们的所有操作=,但无论如何都不会取得多大成就。例如,bool具有与=相同的净效果。

答案 1 :(得分:1)

你为什么不这样做?

enable[0] = enable[0] | true;

答案 2 :(得分:1)

你应该可以很容易地自己制作一个。类似的东西:

std::vector<bool>::reference& operator |= (std::vector<bool>::reference& a, bool b)
{
    if (b)
       a = true;
    return a;
}

或者,std::bitset非常合适。

答案 3 :(得分:0)

简短而甜蜜的回答:应该避免使用std::vector<bool>。请改用vector<wchar>。你实际上得到了一个容器,其中bool以比特打包,这给出了与其他向量不同的行为,慢速代码并且没有人关心回合内存。我想现在没有人喜欢这个了,但是倒转时钟会打破太多的代码......