I have a situation similar to the following
struct Cell
{
uint16_t x, y;
// other fields
Cell* right();
Cell* above();
...
}
class Container
{
private:
uint16_t width, height;
Cell* data;
public:
Container(uint16_t width, uint16_t height) :
width(width), height(height), data(new Cell[width*height])
Cell* cellAt(uint16_t x, uint16_y) { &data[x*height + y]; }
};
Container* container;
Cell* Cell::right() { return container->cellAt(x+1, y); }
...
I trimmed down much of code (eg range checks and whatnot) just to show the design.
Basically this allow me everywhere in the code to access neighbour cells without passing by Container object directly (which would produce more verbose code and neighbours are accesses hundreds of times all around the code base). The solution works nicely and Container
class is not even need to be known around the code, since Cell
is enough.
This approach has a strong limit though: it allows only one instance of Container
. Now I find myself in the situation of wanting multiple instances of Container
, with independent Cell
arrays but I don't want to change the structure of the code.
I'm thinking about a smart way to allow multiple Container
, with the but
- I want to keep the structure as it is
- I absolutely don't want to store a Container* inside each
Cell
to avoid wasting a lot memory (we're talking in order of million of cells) - I want to keep it as much efficient as possible since these neighbour functions are used a lot
I was thinking about allocating width*height + 1
Cell
instances and use the first instance to store a Container*
in its memory, but the problem is how to compute the address of the first Cell considering that the total width/height are fields of Container
itself (and not known by Cell
).
So I guess I should store at least one pointer to Container*
for each column (they are stored by column as shown by cellAt
function for secondary reasons useless to the question). This would waste height*sizeof(Cell)
bytes for each Container
which could be quite a lot but I guess there's no way with with a single pointer.
So basically I could do something like:
Container** container = reinterpret_cast<Container**>(&data[0])
*container = this;
And then retrieve the object. Of course this is a dirty hack which could give problems on architecture which doesn't support unaligned accesses if sizeof(Cell) % alignof(void*) != 0
.
Are there smarter solutions which I'm missing?
Aucun commentaire:
Enregistrer un commentaire