运算符 |= std::vector<bool>
operator |= on std::vector<bool>
以下代码无法编译
#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’)
在我的实际代码中,我有一个位字段,其中包含我想要 |=
函数结果的值。
有很简单的方法可以表达相同的想法,但是有什么好的理由不提供这样的运算符吗?
你为什么不做下面的事情呢?
enable[0] = enable[0] | true;
你应该可以很容易地自己制作一个。类似于:
std::vector<bool>::reference& operator |= (std::vector<bool>::reference& a, bool b)
{
if (b)
a = true;
return a;
}
或者,std::bitset 很合适。
主要原因是 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
unsigned char 数组,它消耗的内存将是 100
字节(假设没有过度分配)。如果 vector<bool>
实际上包含一个 800
bool
的数组,它的内存使用量将至少为 800
字节(因为 sizeof(bool) 必须至少为 1
,根据定义)。
为了允许 vector<bool>
的实现者进行此类内存优化,vector<bool>::operator[]
的 return 类型(即 std::vector<bool>::reference
)不能简单地是 bool &
。在内部,它可能包含对基础类型的引用(例如 unsigned char
)和跟踪它实际影响的位的信息。这将使所有 op=
运算符(+=
、-=
、|=
等)在基础类型上的操作有些昂贵(例如位摆弄)。
std::vector<bool>
的设计者将面临
之间的选择
指定std::vector<bool>::reference
支持所有
op=
并不断听到关于运行时效率低下的抱怨
使用这些运算符的程序员
不支持那些认为这些事情没问题的程序员=
和现场投诉("cleaner code"等),即使它们效率低下。
看来 std::vector<bool>
的设计者选择了选项 2。结果是 std::vector<bool>::reference
支持的唯一赋值运算符是常用标准 operator=()
(操作数为reference
,或类型 bool
) 不是任何操作 =
。这种选择的优点是,如果程序员试图做一些在实践中实际上是糟糕选择的事情,就会出现编译错误。
毕竟,尽管 bool
支持所有操作 =
使用它们并没有取得多大的成就。例如,some_bool |= true
与 some_bool = true
具有相同的净效果。
简短而甜蜜的回答:std::vector<bool>
应该避免。请改用 vector<wchar>
。你实际上得到了一个容器,其中 bools 被打包成位,这给出了与其他向量不同的行为,缓慢的代码并且没有人关心内存。我想现在没有人喜欢这个了,但时光倒流会破坏太多代码...
以下代码无法编译
#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’)
在我的实际代码中,我有一个位字段,其中包含我想要 |=
函数结果的值。
有很简单的方法可以表达相同的想法,但是有什么好的理由不提供这样的运算符吗?
你为什么不做下面的事情呢?
enable[0] = enable[0] | true;
你应该可以很容易地自己制作一个。类似于:
std::vector<bool>::reference& operator |= (std::vector<bool>::reference& a, bool b)
{
if (b)
a = true;
return a;
}
或者,std::bitset 很合适。
主要原因是 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
unsigned char 数组,它消耗的内存将是 100
字节(假设没有过度分配)。如果 vector<bool>
实际上包含一个 800
bool
的数组,它的内存使用量将至少为 800
字节(因为 sizeof(bool) 必须至少为 1
,根据定义)。
为了允许 vector<bool>
的实现者进行此类内存优化,vector<bool>::operator[]
的 return 类型(即 std::vector<bool>::reference
)不能简单地是 bool &
。在内部,它可能包含对基础类型的引用(例如 unsigned char
)和跟踪它实际影响的位的信息。这将使所有 op=
运算符(+=
、-=
、|=
等)在基础类型上的操作有些昂贵(例如位摆弄)。
std::vector<bool>
的设计者将面临
指定
std::vector<bool>::reference
支持所有 op=
并不断听到关于运行时效率低下的抱怨 使用这些运算符的程序员不支持那些认为这些事情没问题的程序员
=
和现场投诉("cleaner code"等),即使它们效率低下。
看来 std::vector<bool>
的设计者选择了选项 2。结果是 std::vector<bool>::reference
支持的唯一赋值运算符是常用标准 operator=()
(操作数为reference
,或类型 bool
) 不是任何操作 =
。这种选择的优点是,如果程序员试图做一些在实践中实际上是糟糕选择的事情,就会出现编译错误。
毕竟,尽管 bool
支持所有操作 =
使用它们并没有取得多大的成就。例如,some_bool |= true
与 some_bool = true
具有相同的净效果。
简短而甜蜜的回答:std::vector<bool>
应该避免。请改用 vector<wchar>
。你实际上得到了一个容器,其中 bools 被打包成位,这给出了与其他向量不同的行为,缓慢的代码并且没有人关心内存。我想现在没有人喜欢这个了,但时光倒流会破坏太多代码...