97

正如(希望)我们都知道的那样,vector<bool>它完全被破坏了,不能被视为 C 数组。获得此功能的最佳方法是什么?到目前为止,我想到的想法是:

  • 使用 avector<char>代替,或
  • 使用包装类并拥有vector<bool_wrapper>

大家是怎么处理这个问题的?我需要这个c_array()功能。

作为一个附带问题,如果我不需要该c_array()方法,如果我需要随机访问,解决此问题的最佳方法是什么?我应该使用双端队列还是其他东西?

编辑:

  • 我确实需要动态调整大小。
  • 对于那些不知道的人,vector<bool>是专门的,因此每个bool需要 1 位。因此,您不能将其转换为 C 样式的数组。
  • 我想“包装器”有点用词不当。我在想这样的事情:

当然,my_bool由于可能的对齐问题,我必须阅读 a :(

struct my_bool
{
    bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
4

8 回答 8

42

std::deque如果您不需要阵列,请使用,是的。

vector否则,请使用不专注于的替代方案bool,例如Boost Container中的替代方案。

于 2009-03-22T00:29:16.613 回答
23

这是一个有趣的问题。

如果您需要 std::vector 如果它不是专门的,那么它可能适用于您的情况:

#include <vector>
#include <iostream> 
#include <algorithm>

class Bool
{
public:

    Bool(): m_value(){}
    Bool( bool value ) : m_value(value){}

    operator bool() const { return m_value; }

    // the following operators are to allow bool* b = &v[0]; (v is a vector here).
    bool* operator& () { return &m_value; }
    const bool* operator& () const { return &m_value; }

private:

    bool m_value;

};




int main()
{
    std::vector<Bool> working_solution(10, false);


    working_solution[5] = true;
    working_solution[7] = true;


    for( int i = 0; i < working_solution.size(); ++i )
    {
        std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::sort( working_solution.begin(), working_solution.end());
    std::cout<< "--- SORTED! ---" << std::endl;

    for( int i = 0; i < working_solution.size(); ++i )
    {
            bool* b = &working_solution[i]; // this works!

        std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct
    }

    std::cin.get();
    return 0;
}

我用 VC9 试过这个,它似乎工作正常。Bool 类的想法是通过提供相同的行为和大小(但不是相同的类型)来模拟 bool 类型。几乎所有的工作都是由 bool 运算符和这里的默认复制构造函数完成的。我添加了一种排序,以确保它在使用算法时做出假设。

不确定它是否适合所有情况。如果它适合您的需求,那么它会比重写类似矢量的类更少工作......

于 2009-03-22T01:20:20.830 回答
19

取决于你的需要。我会去std::vector<unsigned char>。如果您只使用功能的子集,编写包装器可能会很好,否则它将成为一场噩梦。

于 2009-03-22T00:30:12.697 回答
13

大家是怎么处理这个问题的?我需要 c_array() 功能。

boost::container::vector<bool>

vector < bool > 特化一直存在很大问题,并且曾多次尝试将其从标准中弃用或删除,但均未成功。Boost.Container没有实现它,因为有一个优越的Boost.DynamicBitset解决方案。

...

所以boost::container::vector::iterator返回真正的 bool 引用并作为一个完全兼容的容器工作。如果您需要boost::container::vector < bool > 功能的内存优化版本,请使用Boost.DynamicBitset

于 2013-04-12T03:13:09.800 回答
6

考虑使用向量< int >。一旦您通过了编译和类型检查,bool 和 int 都只是机器字(编辑:显然这并不总是正确的;但在许多 PC 架构上都是正确的)。如果您想在没有警告的情况下进行转换,请使用“bool foo = !!bar”,它将零转换为假,非零转换为真。

vector< char > 或类似的将使用更少的空间,尽管在某些情况下它也有可能(非常小的)速度受到影响,因为字符小于机器字长。我相信,这是使用整数而不是字符来实现布尔值的主要原因。

如果你真的想要干净的语义,我也喜欢制作你自己的布尔类的建议——看起来像一个布尔,行为像一个布尔,但愚弄了模板专业化。

此外,欢迎加入希望从 C++ 标准中删除 vector<bool> 专业化(用 bit_vector 代替它)的人的俱乐部。这是所有酷孩子们闲逛的地方:)。

于 2009-03-22T09:03:25.037 回答
4

这个问题已经在 comp.lang.c++.moderated 上讨论过了。建议的解决方案:

  • 您自己的分配器(基于std::allocator)和自己的向量专业化;
  • 使用std::deque(早在 S. Mayers 的一本书中就推荐过)——但这不符合您的要求;
  • 制作 PODbool包装器;
  • 使用大小相同的东西(char/ /等)代替; intboolbool

同样早些时候,我看到了标准委员会的提案 - 引入宏(类似于STD_VECTOR_BOOL_SPECIAL)以禁止这种专业化 - 但 AFAIK 这个提案没有在 stl 实现中实现,也没有被批准。

看来你的问题没有办法很好地做到这一点......也许在 C++0x 中。

于 2009-03-22T01:52:21.860 回答
3

最简单的答案是使用vector<struct sb>where sbis struct {boolean b};。然后你可以说push_back({true})。看起来不错。

于 2015-06-23T21:19:30.647 回答
2

我首选的解决方法是一个vector具有基础类型的作用域枚举boolvector<bool>如果委员会没有对其进行专门化,这将非常接近我们的情况。

enum class switch_status : bool { ON, OFF };

static_assert( sizeof( switch_status ) == 1 );

::std::vector<switch_status> switches( 20, switch_status::ON );

static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches.back()  ), switch_status &> );
static_assert( ::std::is_same_v< decltype( switches[ 0 ]    ), switch_status &> );

您将对接受 cast to/from 的智慧有自己的看法bool

enum class switch_status : bool { OFF = false, ON = true };

static_assert( static_cast< bool          >( switch_status::ON  ) == true               );
static_assert( static_cast< bool          >( switch_status::OFF ) == false              );
static_assert( static_cast< switch_status >( true               ) == switch_status::ON  );
static_assert( static_cast< switch_status >( false              ) == switch_status::OFF );
于 2018-10-05T08:21:45.910 回答