bitset類的實現

來源:互聯網
上載者:User

問題:實現一個bitmap類(為避免與stl中的bitset重名),用於位元影像。

測試案例:

BitMap bm(20);bm[3] = 1;bm[5] = 0;bool b = bm[12];

其本質上是用記憶體中的一位來表示某種意義。

痛點在於,使用int或者unsigned int類型儲存多位bool變數(也就是0或者1)後,怎麼重載下標操作符。

如果不使用下標而是使用函數,例如bm.set(3);或者bm.reset(12);一般是很簡單的,只需要重載[]即可。

使用下標操作符的痛點在於:c++不支援bit引用。

但是就是要求使用下標操作(項目中你可以這麼做,但是面試的時候,面試官就要求使用下標),how?


這裡需要使用一種設計模式:代理模式。


先看代碼:

#include <iostream>#include <cassert>/**************************************** * 20130506 微軟實習生面試時悲劇的題目 * 當時根本沒想到代理模式 * 至於代理模式,以前也僅僅是聽說過而已*****************************************/using namespace std;/***************************************** * BitMap bm(20); * bm[9]=1;//set bit * bm[1]=0;//clear*****************************************/class BitMap{    typedef unsigned int UINT;public:    BitMap(size_t bitlen=0):m_len(bitlen)    {        nUINT=m_len/DATALEN+(m_len%DATALEN==0?0:1);        m_data = new UINT[nUINT]();    }    ~BitMap()    {        delete[] m_data;    }    void set(size_t index)    {        assert(0<=index&&index<m_len);        *(m_data+index/DATALEN) = *(m_data+index/DATALEN) | (1<<(index%DATALEN));    }    void reset(size_t index)    {        assert(0<=index&&index<m_len);        *(m_data+index/DATALEN) = *(m_data+index/DATALEN)&(~(1<<(index%DATALEN)));    }    bool test(size_t index)const    {        assert(0<=index&&index<m_len);        return *(m_data+index/DATALEN) & ( 1<<(index%DATALEN));    }    void flip()///~all bits    {        for(unsigned int i=0;i<nUINT;i++)            *(m_data+i) ^= (~0);    }/****  代理模式 ****/    class proxy    {    public:        proxy(BitMap &refbm, size_t index):            rbm(refbm),index(index)            {            }        proxy & operator= (bool val)        {            if(val)                rbm.set(index);            else                rbm.reset(index);            return *this;        }        proxy & operator= (const proxy &rhs)        {            if(rhs.rbm.test(rhs.index))                rbm.set(index);            else                rbm.reset(index);            return *this;        }        operator bool()        {            return rbm.test(index);        }    private:        BitMap &rbm;        size_t index;    };    proxy operator[](size_t index)    {        return proxy(*this,index);    }    const proxy operator[] (size_t index) const    {        return proxy(const_cast<BitMap &>(*this), index);    }private:    UINT *m_data;///實際儲存bit的儲存區    size_t m_len;///位的長度,支援可變長度的位,bitset不支援。    size_t nUINT;///實際使用的UINT的個數    const static int DATALEN = 32;///每個UINT可以儲存的bit個數    friend ostream& operator<< (ostream& out,BitMap &bm);///用於輸出,便於調試};ostream& operator<< (ostream& out,BitMap &bm){    for(int i=bm.m_len-1;i>=0;i--)        out<<bm.test(i);    return out;}void testcase(){    BitMap b(40);    cout<<b<<endl;;    b.set(2);    b.set(3);    cout<<b<<endl;    b.reset(2);    cout<<b<<endl;    b.flip();    cout<<b<<endl;    cout<<"ttt"<<endl;    b[1]=0;    cout<<b<<endl;    b[1]=1;    cout<<b[0]<<endl;}int main(){    testcase();    return 0;}

前面的set、reset、flip等函數的實現就是位元運算,不需要多說。

關鍵在這裡:

b[1]=0;

首先,b[1]將調用下標操作符,

    proxy operator[](size_t index)    {        return proxy(*this,index);    }

這裡返回的是一個proxy對象。proxy怎麼構造的呢?2個參數:BitMap引用和index。這2個參數足以定位到一個具體的bit!也就是說,一個proxy對象對應一個bit。

然後將一個bool值賦值給這個對象,將調用proxy的賦值操作符:

        proxy & operator= (bool val)        {            if(val)                rbm.set(index);            else                rbm.reset(index);            return *this;        }

這樣就修改了BitMap對象的某一位。


還有一處需要說明的地方:

        operator bool()        {            return rbm.test(index);        }

這裡定義了類型轉換,可以將一個proxy對象轉換為一個bool變數。讀取的時候,例如bool  b=bm[2];將調用這個函數。


這樣,對外看來,使用下標訪問的就是BitMap對象中的某一位,可以進行讀或者寫的操作。

很巧妙的設計。


/*********************************************分****割****線***************************************************************/

關於代理模式:

代理模式的定義:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在用戶端和目標對象之間起到中介的作用。

直接看這些定義,感覺理解起來很不方便。

有了這個例子,體會得深的多了。

有人說:

“設計模式就是編程思想,很多新手覺得好像都看懂了但不會用,因為編程思想還沒達到那個層次!

這個要靠點點滴滴的積累,當你積累了10W行有效代碼,再回過頭去看設計模式,自然會有豁然開朗的感覺

架構要用,“不要重複造輪子”,但是要關注架構的實現原理”


深有體會!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.