0

我正在尝试创建一个 BoolArray 类,它表示一个布尔数组,而不是为每个布尔变量保存 1 个布尔值。它使用 1 个字符变量来表示 8 个使用位的布尔值,并节省内存。我想使用运算符 [] 使它像普通数组一样方便。

我可以使用 arr[5] 并为第五位返回一个布尔值。我的问题是分配了一点。我无法引用一位,因此我需要创建一个执行该任务的函数。我的问题是是否可以使用运算符重载来控制数组样式分配。我的解决方案是使用另一个类(MyBoolean)并将其作为对 BoolArray 运算符 [] 的引用返回。MyBoolean 重载 operator= 并更改 BoolArray 的位。有没有一种更简单的方法可以重载 operator[]= 或类似的东西?

#include <iostream>
#include <tgmath.h>
using namespace std;



string int_to_binary_string(int number)
{
    if ( number == 0 ) return "0";
    if ( number == 1 ) return "1";

    if ( number % 2 == 0 )
        return int_to_binary_string(number / 2) + "0";
    else
        return int_to_binary_string(number / 2) + "1";
}




class MyBoolean;
class BoolArray {

    private:
        unsigned char* arr;
        int size;


        void setBit(int bit_number,bool value);

    public:
        explicit BoolArray(int size);       
        ~BoolArray();
        MyBoolean operator[](unsigned int index);
        int getSize() const;

        friend class MyBoolean;
};



// ***************************** MyBoolean *********************************
class MyBoolean {

    private:
        bool value;
        int bit_number;
        BoolArray* bool_array;

    public:
        // --- Constructor ---
        MyBoolean(bool value,int bit_number,BoolArray* bool_array) :
            value(value),bit_number(bit_number),bool_array(bool_array)
        {}


        // --- cast ---
        operator bool() const{
            return value;
        }

        MyBoolean& operator=(bool new_value) {
            value = new_value;
            bool_array->setBit(bit_number,new_value);
        }
};



// ***************************** BoolArray *****************************
    void BoolArray::setBit(int bit_number,bool value) {
            int index = floor((double)bit_number/8);
            bit_number -= index*8;

            cout << "trying to set " << bit_number << " to " << value << endl;

            if(value==true) {
                int binary_num = pow(2,bit_number);
                cout << "arr[index]: " << int_to_binary_string(arr[index]) << " - binary_num: " << int_to_binary_string(binary_num);
                arr[index] = arr[index] | binary_num; 
                cout << " - after: " << int_to_binary_string(arr[index]) << endl;
            }
            else {
                int binary_num = 0 | 255;
                int binary_num_2 = pow(2,bit_number);
                binary_num = binary_num^binary_num_2;
                arr[index] = arr[index] & binary_num;
            }
    }


    // --- Constructor ---
    BoolArray::BoolArray(int size) :
        size(size)
    {
        size = ceil((double)size/8);
        arr = new unsigned char[size];
    }


    // --- Destructor ---
    BoolArray::~BoolArray() {
        delete[] arr;
    }


    // --- operator[] ---
    MyBoolean BoolArray::operator[](unsigned int index) {
        if(index>size-1)
            throw "error";

        int arr_index = floor((double)index/8);
        int bit_number = index - arr_index*8;
        unsigned int binary_num = pow(2,bit_number);
        int value= false;
        if((arr[arr_index] & binary_num)>0)
            value = true;

        MyBoolean my_bool(value,index,this);

        return my_bool;
    }


    // --- size ---
    int BoolArray::getSize() const {
        return size;
    }



ostream& operator<<(ostream& os, MyBoolean b) {
    os << (bool) b;
    return os;
}

ostream& operator<<(ostream& os,BoolArray& arr) {
    for(int i=0;i<arr.getSize();i++)
        os << arr[i] << "->";
    return os;
}


int main() {
    BoolArray arr(12);
    arr[0] = true;
    arr[1] = false;
    arr[2] = true;
    arr[3] = false;
    arr[4] = true;
    arr[5] = false;
    arr[6] = true;
    arr[7] = false; 
    arr[8] = true;
    arr[9] = false;
    arr[10] = true;
    arr[11] = false;    
    cout << arr;
    return 0;
}
4

3 回答 3

2

您基本上已经有了最好的解决方案:创建一个可从 bool 分配但在内部仅分配 1 位的代理类,并且可以隐式转换为bool. BoolArray将从中返回此代理类operator[]

事实上,这vector<bool>就是vector<bool>::reference. 正如评论者所说,std::vector专门用来bool做你正在写的东西。因此,除非这只是为了学习,否则您所写的内容是无用/多余的。

于 2013-06-16T12:22:17.727 回答
2

正如评论者建议你的那样,使用std::bitset. 不是推倒重来

但是如果你想做一个练习,并实现一个 bitset,答案是否定的。

事实上,你所做std::bitset正是你正在做的:使用存储位的值和位置的代理类。

请检查第00760行(代理类声明)和01138(非常量运算符 [] 的声明和实现)。

于 2013-06-16T12:27:11.397 回答
0

像你一样使用代理对象,基本上是正确的做法。但是:您永远不应该使用浮点运算来进行整数运算(它们不精确,有时精度很低):

// Don't do this:
int index = floor((double)bit_number/8);
// But this:
int index = bitnumber/8;

整数除法总是向零舍入,floor(x)不需要使用。

// Don't do this:
int binary_num = pow(2,bit_number);
// But this:
int binary_num = 1 << bit_number;

除了在舍入为整数后可能会给出错误的结果外,pow(a,b)它比使用位移运算符要慢得多。

于 2013-06-16T15:14:14.643 回答