vector <bool>的替代方法


90

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

  • 使用一个vector<char>代替,或
  • 使用包装器类并具有 vector<bool_wrapper>

你们如何处理这个问题?我需要c_array()功能。

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

编辑:

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

当然,my_bool由于可能的对齐问题,我不得不读一读:(

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

2
有什么理由不使用... C样式数组吗?
kquinn

rlbond,您需要动态尺寸吗?
Johannes Schaub-litb

16
好吧,我会咬人-您为什么认为向量是“完全破坏”的?
Andrew Grant

8
@安德鲁·格兰特(Andrew Grant)-参见open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2160.html
丹尼尔·

4
有趣的是,vector<bool>这只是在我的代码中引起了数据争用错误,因为我期望不同的线程能够安全地同时修改向量中的不同元素。使用解决deque<bool>
Andres Riofrio

Answers:



21

那是一个有趣的问题。

如果您需要不专门的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运算符和此处的默认副本构造函数完成。我添加了一种排序方式,以确保它在使用算法时能够像假定的那样做出反应。

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


“我们可以添加bool *运算符&(){return&m_value;}”-错误。ISO:“ sizeof(bool)不需要是1
Evgeny Panasyuk

2
我宁愿将更operator bool() const改为operator bool&()。这使得它更好地反映了简单布尔的行为,因为它支持分配等。在某些情况下,例如v[0] = true;我确实看不到此更改有问题,那么我可以进行编辑吗?
Agentlien 2014年

19

取决于您的需求。我要么去std::vector<unsigned char>。如果仅使用部分功能,则可以编写包装器,否则将成为噩梦。


unsigned char始终为单个字节,而实现uint8_t可能不支持。uint_fast8_t可以工作,但如果其目的是要清楚这是一个单字节,而不是一个角色,但你还不如用std::byte那么
加布里埃尔拉维耶

13

你们如何处理这个问题?我需要c_array()功能。

boost::container::vector<bool>

vector < bool >专业化一直存在很多问题,并且有过多次尝试将其弃用或从标准中删除。Boost.Container没有实现它,因为有一个高级的Boost.DynamicBitset解决方案。

...

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


6

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

vector <char>或类似的东西将使用更少的空间,尽管在某些情况下它也有可能受到(非常小的)速度冲击,因为字符小于机器字的大小。我认为,这是使用int而不是char来实现布尔的主要原因。

如果您真的想要干净的语义,我也喜欢创建自己的布尔类的建议-看起来像布尔,行为像布尔,但是愚弄了模板专业化。

另外,欢迎那些想要vector <bool>专业化脱离C ++标准(使用bit_vector代替)的人们加入。这是所有很酷的孩子都闲逛的地方:)。


4

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

  • 您自己的分配器(基于std::allocator)和自己的向量专门化;
  • 使用std::deque(早在S. Mayers的一本书中就建议使用)-但这不是您的要求;
  • 做POD bool包装;
  • 使用大小与(char/ int/ etc)相同的东西bool代替bool

也是很早以前,我看到了标准委员会的提案-介绍宏(类似 STD_VECTOR_BOOL_SPECIAL)来禁止这种专业化-但是AFAIK这项提案并未在stl实施中实施,也未获得批准。

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


3

简单的答案是用vector<struct sb>哪里sbstruct {boolean b};。那你可以说push_back({true})。好像很好


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 &> );

您将对以下演员的演员表发表看法有自己的见解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 );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.