在 C++ 中使用 std::vector<bool> 对象是不是可以接受,还是应该使用替代方法?

Posted

技术标签:

【中文标题】在 C++ 中使用 std::vector<bool> 对象是不是可以接受,还是应该使用替代方法?【英文标题】:Is the use of std::vector<bool> objects in C++ acceptable, or should I use an alternative?在 C++ 中使用 std::vector<bool> 对象是否可以接受,还是应该使用替代方法? 【发布时间】:2011-10-10 13:15:31 【问题描述】:

我正在使用用户定义的位数(我持有一个 3 维位数组,因此大小按立方增加 - 假设不少于 512 位),并且需要分别翻转它们。现在,我只是在电脑上使用bool 类型,因为内存不是问题。我确实计划将来将代码移至微控制器,因此处理能力和内存要求可能是一个问题。不过现在,我只想要速度。

然后我从C++ STL 中找到了std::bitset 对象,但我无法在运行时定义位集的大小。然后我发现std::vector&lt;byte&gt; 有一个特殊的初始化程序将它们存储为位(而不是整个字节或 4 个字节),但后来在***中找到了this section:

标准库定义了vector 模板的特化 为bool。该专业的描述表明 实现应该打包元素,以便每个bool 只使用 一点的内存。这被广泛认为是一个错误。 [...] C++ 标准委员会和库工作组普遍认为,vector&lt;bool&gt; 应该被弃用并随后从标准库中删除,而该功能将以不同的名称重新引入。

现在,您可能会看到我想要使用 vector&lt;bool&gt; 对象,但在阅读之后,我正在考虑使用其他东西。唯一的问题是我不确定要使用 什么。我很好奇为什么他们说应该重新引入功能(尽管名称不同)。

所以,我的问题是,使用 vector&lt;bool&gt; 对象是否可以接受(因为它们是 STL 的一部分)?它们是 C++ 标准的一部分吗?

如果它们的使用不可接受,是否有可接受的替代解决方案(在我之外自己定义一个特殊容器)?我自己有一些想法,但我只是好奇是否有人有更好的解决方案。另外,我想避免使用大型库(同样,我希望最终将此代码移植到微控制器)。

【问题讨论】:

仅使用vec[bit&gt;&gt;3] |= (1&lt;&lt;(bit&amp;7));std::vector&lt;unsigned char&gt; 有什么问题? 【参考方案1】:

In "Effective STL," Item 18,Scott Meyers 推荐:“避免使用向量。”:

作为一个 STL 容器,确实只有两点不妥 矢量。首先,它不是 STL 容器。其次,它不 持有布尔值。除此之外,没有什么可反对的。

【讨论】:

【参考方案2】:

vector&lt;bool&gt; 没有任何问题,只是它不等同于 vector&lt;T&gt;,因为 T 是等同于 bool 的整数类型。这仅显示在性能(CPU 一次仅访问字节,其中 vector&lt;bool&gt; 中的每个元素都存储在一个位中)和内存访问(对 vector&lt;bool&gt; 的第一个元素的引用不等同于类似的数组与任何其他vector&lt;T&gt;

不幸的是,它是标准的一部分:参见 23.3.7 (C++0x FDIS) 部分。

【讨论】:

vector 针对空间而非速度进行了优化。它也不像 vector 那样确认容器语义。【参考方案3】:

批评是vector&lt;bool&gt; 是唯一不完全符合标准容器要求的标准容器。有点意外。

另一点是vector&lt;bool&gt; 强制每个人进行空间优化(通过存储位),而某些用户可能更喜欢速度优化。

除此之外,主要的偏差是容器不能返回对其成员的引用,因为它不存储任何布尔值。这将使奇怪的标准库算法无法为vector&lt;bool&gt; 编译。

如果你能接受它,并且它满足对其他一切的需求,那么使用它是完全可以的。

【讨论】:

【参考方案4】:

boost.dynamic_bitset 几乎与 std::bitset 相同,只是它的大小是在运行时给出的。如果你对 boost 依赖不感兴趣,它的源代码(完全包含在它的头文件中)至少可以提供更多关于如何编写这种容器的想法。

【讨论】:

感谢您的回复,我更改了我的问题以更准确地反映我选择 512 的原因(我正在使用的网格是 8x8x8,但它可以定义为任何大小,因此元素的数量 [以及因此内存需求] 立方增加)。 @Breakthrough 没关系我在 512 上的注释,但是那个潜在的大型 3D 数组中的数据有任何内部结构吗?也许还有其他数据结构可以利用它,比如 en.wikipedia.org/wiki/K-d_tree en.wikipedia.org/wiki/Octree 和朋友? +1,您的答案没有任何问题,我非常感谢那些替代数据类型,但@rubenvb 发布了一个更适合我正在寻找的答案。在这种情况下,我不认为树是要走的路,因为我没有执行任何二进制搜索。但是,我确实需要几乎立即以无特定顺序访问此数组中的任何元素...【参考方案5】:

vector&lt;bool&gt; 的正确使用没有什么问题,就像auto_ptr 没有什么问题一样——只要你在继续之前知道缺点和惊喜。

【讨论】:

确实如此。如果vector&lt;bool&gt; 适合您,请使用它。这是标准的一部分。如果安全使用,将来删除专业化时最糟糕的情况不是您的代码会中断,而是它会突然使用更多的 RAM。 不要使用auto_ptr。它在 C++11 中被弃用并在 C++17 中被删除。【参考方案6】:

我建议使用BITSCAN 库作为 Boost:dynamic_bitset 的替代方案。比较调查可以找到here。

【讨论】:

【参考方案7】:

替代方案可能是 BitMagic,尽管我不确定它是否适用于 x86 以外的任何其他架构(它使用 SIMD 进行了高度优化)。

【讨论】:

以上是关于在 C++ 中使用 std::vector<bool> 对象是不是可以接受,还是应该使用替代方法?的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::vector::swap 方法在 C++ 中交换两个不同的向量是不是安全?

在 C++ 中检查 std::vector<string> 是不是包含某个值 [重复]

包装 std::vector 的 std::vectors,C++ SWIG Python

将 std::vector<double> 从 C++ 包装到 C 以在 Swift 中使用

通过 mpi 发送一个 c++ std::vector<bool>

C++随机选择std::vector的非空元素<std::vector>>