bool数组的最小大小实现

时间:2013-03-11 11:26:41

标签: c++ bit-manipulation

我需要一个bool数组的最小大小实现。数组的大小在编译时是已知的。

我检查了std::bitsetboost::array,但它们都会产生对小数组很重要的开销。例如,如果数组大小 8 ,则容器应仅使用 1字节的内存(假设通用CPU架构)。

这是否存在或我是否需要自己动手?

编辑:这是我最后的实施,基于Tom Knapen的帖子。 我为构造函数添加了一个默认值,并在越界索引的情况下添加了throw。 非常感谢汤姆和其他所有人。

#include <stdexcept>
#include <climits>

/// Minimum size container for bool-arrays
/**
 * TODO: may want to add to_uint32_t accessor and the like
 * for sufficently small arrays
 */
template<int SIZE>
class bitarray
{
public:
    bitarray(bool initial_value = false);

    bool get(int index) const;
    void set(int index, bool value);

private:
    static const int ARRAY_SIZE = (SIZE + CHAR_BIT - 1) / 8;
    unsigned char mBits[ARRAY_SIZE];
};

// ----------------------------------------------------
//      Definitions
// ----------------------------------------------------

template<int SIZE>
inline bitarray<SIZE>::bitarray(bool initial_value)
{
    for(int i = 0; i < ARRAY_SIZE; ++i)
        mBits[i] = initial_value ? -1 : 0;
}

template<int SIZE>
inline bool bitarray<SIZE>::get(int index) const
{
    if (index >= SIZE)
        throw std::out_of_range("index out of range");
    return (mBits[index / CHAR_BIT] & (1 << (index % CHAR_BIT)));
}

template<int SIZE>
inline void bitarray<SIZE>::set(int index, bool value)
{
    if (index >= SIZE)
        throw std::out_of_range("index out of range");
    if (value)
        mBits[index / CHAR_BIT] |= (1 << (index % CHAR_BIT));
    else
        mBits[index / CHAR_BIT] &= ~(1 << (index % CHAR_BIT));
}

5 个答案:

答案 0 :(得分:3)

您可以自己制作,但不能从头开始制作。 bitset实现应该有几行看起来像typedef unsigned long _WordT;(SGI)或typedef _Uint32t _Ty;(MSVS)。您可以小心地替换类型和命名空间,并以这种方式创建自己的容器。我将类型更改为char,sizeof返回1(vs {pastebin上的vs2010概念验证)

答案 1 :(得分:2)

这是一个简单的例子。请注意,它只执行它所需要的,因此您将无法像std :: bitset那样迭代它。

#include <climits>
#include <iostream>
#include <cassert>

template<int S> struct boolset {
    static int const SIZE = ((S / CHAR_BIT) + (0 != (S % CHAR_BIT)));
    unsigned char m_bits[SIZE];
public:
    boolset() : m_bits() { for(int i = 0; i < SIZE; ++i) m_bits[i] = 0; }

    bool get(int i) const {
        assert(i < S);
        return (m_bits[i / CHAR_BIT] & (1 << (i % CHAR_BIT)));
    }

    void set(int i, bool v) {
        assert(i < S);
        if(v) { m_bits[i / CHAR_BIT] |= (1 << (i % CHAR_BIT)); }
        else { m_bits[i / CHAR_BIT] &= ~(1 << (i % CHAR_BIT)); }
    }

    void print(std::ostream & s) const {
        for(int i = 0; i < S; ++i) {
            s << get(i);
        }
    }
};

int main(int argc, char ** argv) {
    std::cout << sizeof(boolset<1>) << std::endl;
    std::cout << sizeof(boolset<8>) << std::endl;
    std::cout << sizeof(boolset<9>) << std::endl;
    std::cout << sizeof(boolset<16>) << std::endl;
    std::cout << sizeof(boolset<17>) << std::endl;
    std::cout << sizeof(boolset<32>) << std::endl;
    std::cout << sizeof(boolset<33>) << std::endl;
    std::cout << sizeof(boolset<64>) << std::endl;
    std::cout << sizeof(boolset<129>) << std::endl;
    std::cout << std::endl;
    boolset<31> bs;
    bs.set(0, true);
    bs.set(28, true);
    bs.set(2, true);
    std::cout << bs.get(28) << std::endl;
    bs.print(std::cout); std::cout << std::endl;
    bs.set(2, false);
    bs.print(std::cout); std::cout << std::endl;
}

ideone上的输出。

答案 2 :(得分:2)

template <int N>
class BitSet {
    enum { BPC = 8 }; // Bits per char, #ifdef as needed
    char m_bits[ (N + (BPC-1)) / BPC ];
public:
void SetBit( int i ) { m_bits[ i / BPC ] |= 1 << (i % BPC); }
void ClearBit( int i ) { m_bits[ i / BPC ] &= ~(1 << (i % BPC)); }
int GetBit( int i ) { return (m_bits[ i / BPC ] >> (i % BPC)) & 1; }
};

答案 3 :(得分:1)

也许你做过这样的事情:

#include<vector>
#include <iostream>
template<int N>
struct array
{
   char bits : N;

   int getNthbit(int bitnr)
   {
      // important to make sure bitnr is not larger than the size of the type of `bits` in number of `CHAR_BITS` 
      return bits & (1 << bitnr);
   }
};

//Specialize for N > 8

int main()
{
   std::cout << sizeof(array<8>);
}

如果查看Live Example,您会看到当N == 8时,它会为sizeof(array<8>)返回1。

当你输入32时它返回4.

您唯一需要做的就是专门为N&gt;设计模板。 8,以便类型更改以适合位数。

我不是模板天才,也许有人愿意写一个例子?

答案 4 :(得分:0)

免责声明:我从 OP 问题中提取了这个答案。 Answers should not be contained in the question itself.


Gabriel Schreiber 提供的答案:

这是我基于 post of Tom Knapen 的最终实现。 我为构造函数添加了一个默认值,并在索引越界的情况下添加了 throwing。 非常感谢汤姆和其他所有人。

#include <stdexcept>
#include <climits>

/// Minimum size container for bool-arrays
/**
 * TODO: may want to add to_uint32_t accessor and the like
 * for sufficently small arrays
 */
template<int SIZE>
class bitarray
{
public:
    bitarray(bool initial_value = false);

    bool get(int index) const;
    void set(int index, bool value);

private:
    static const int ARRAY_SIZE = (SIZE + CHAR_BIT - 1) / 8;
    unsigned char mBits[ARRAY_SIZE];
};

// ----------------------------------------------------
//      Definitions
// ----------------------------------------------------

template<int SIZE>
inline bitarray<SIZE>::bitarray(bool initial_value)
{
    for(int i = 0; i < ARRAY_SIZE; ++i)
        mBits[i] = initial_value ? -1 : 0;
}

template<int SIZE>
inline bool bitarray<SIZE>::get(int index) const
{
    if (index >= SIZE)
        throw std::out_of_range("index out of range");
    return (mBits[index / CHAR_BIT] & (1 << (index % CHAR_BIT)));
}

template<int SIZE>
inline void bitarray<SIZE>::set(int index, bool value)
{
    if (index >= SIZE)
        throw std::out_of_range("index out of range");
    if (value)
        mBits[index / CHAR_BIT] |= (1 << (index % CHAR_BIT));
    else
        mBits[index / CHAR_BIT] &= ~(1 << (index % CHAR_BIT));
}