Bittömb
Czirkos Zoltán · 2022.06.21.
Pakolt tömb indexelése
Ha egy pakolt tömbünk van, ahol egy bájton belül több elemet tárolunk (ilyen például egy bittömb, amelyik minden bitet
használ), akkor az egyes elemeket nem tudjuk megcímezni. A legkisebb címezhető memóriaegység ugyanis a char
.
Ilyenkor közvetlenül nem lehet rendes indexelő operátort csinálni; a kiválasztott elemnek ugyanis nem tudjuk referenciáját visszaadni sem.
Helyette a lenti megoldás használható. Az indexelő operátor egy kis segédobjektumot ad vissza. Jelen esetben az objektum
bool
-lá alakító operátora a bitet adja vissza; az operator=(bool)
-ja pedig a hivatkozott bitet
változtatja.
#include <iostream>
#include <cstdint>
class BitTomb {
private:
uint32_t c = 0; /* legyen most ez a tömb :) */
public:
BitTomb() = default;
/* Proxy osztályocska, ilyet ad vissza a BitTömb operator [].
* Ennek két átdefiniált operátora: bool-lá alakítás és bool értékadás. */
class Proxy {
/* megjegyzi magának, melyik bittömb melyik indexéről van szó. */
BitTomb *ezen;
int index;
public:
Proxy(BitTomb *bt, int i): ezen(bt), index(i) {}
operator bool () const {
return (ezen->c >> index) & 1;
}
Proxy& operator=(bool uj) { /* bitseged=bool */
if (uj) { /* 1-be kell */
ezen->c |= 1<<index;
} else { /* 0-ba kell */
ezen->c &= ~(1<<index);
}
return *this;
}
/* Ez egy NAGYON furcsa operator=. Ugyanis ha azt írjuk,
* hogy b[1] = b[2], akkor Proxy = Proxy értékadás történik.
* Ilyenkor viszont nem a proxyt kell másolni,
* hanem a hivatkozott biteket! */
Proxy& operator=(const Proxy& masik) {
*this = bool(masik); /* this->operator=(masik.operator bool()); */
return *this;
}
};
Proxy operator[](int i) {
return Proxy(this, i);
}
};
int main() {
BitTomb b;
b[3] = 1; /* operator=(bool uj); */
std::cout << b[3] << std::endl; /* operator bool() */
std::cout << b[5] << std::endl;
b[5] = b[3]; /* Proxy::operator=(Proxy) */
std::cout << b[5] << std::endl;
}
Így működik egyébként az std::vector<bool>
specializáció is. Ezért nem
lehet egy bool
vektor egy elemének a címét sem képezni; akkor nem az adott
bool
címét képeznénk, hanem a segédobjektumét. Amúgy is, egy bitnek nem lehet memóriacíme:
a legkisebb egység, aminek van, a bájt.