Local static class fields

Simen Kjærås simen.kjaras at gmail.com
Tue Aug 13 08:40:07 UTC 2019


On Monday, 12 August 2019 at 22:48:43 UTC, Bert wrote:
> Making a field static is effectively a global variable to the 
> class.
>
> I have a recursive class structure(think of a graph or tree) 
> and I need to keep a global state for it, but this state 
> actually needs to be different for each tree object. The reason 
> for this is that structurally it will not change per tree and 
> if it it is not static then it wastes space unnecessarily.
>
> class X
> {
>     X[] x;
>     static State s;
> }
>
> making s non-static has the problem that every X will allocate 
> storage for s wasting space since for any instance chain of X's 
> they will all have the same s. Making it static though then 
> makes it the same for all instance chain's of X, of which it 
> should be local to each.
>
> One way around this is to use an dictionary that associates 
> each state to each instance chain.
>
> That is there is a initial X that is the parent of the chain 
> and we can then associate a state to it's address, any other 
> chain will have a different initial X and so we can get a new 
> state.
>
> class X
> {
>     X[] x;
>     static State[X] s;
> }
>
>
> This is not a huge difficulty to do but does require finding 
> the initial X to use, which is not difficult but wastes cycles 
> for large chains. There will, of course, be a constructor that 
> constructs a chain and creates a new state for it and updates s.
>
>
> Is there any way to do this more naturally in D?

First: Are you low on memory? Is traversing the tree actually 
slow? Since you don't know which of these issues to prioritize, 
in all likelihood the answer to both questions is no, and you 
should use the solution that's easier to read.

Of course, that's not the answer you want to hear. Let's consider 
the alternatives:

1) Embed it in each node. Costs 1 pointer's worth of memory per 
node. Very fast. Very easy to understand.

2) Use a dictionary with entries for each node. Costs more than 1 
pointer's worth of memory per node. Fast, but not quite as fast 
as 1). 1) is almost definitely a better option.

3) Use a dictionary with entries for each root node. Costs more 
than 1 pointer's worth of memory, but per tree instead of per 
node. Requires traversal of the tree to find the root, so slower 
than both 1) and 2), especially for deep hierarchies. Complicated 
code.

4) Use a derived class for the root node (class RootX : X { State 
s }). Still requires traversing the tree to find the root, likely 
via a virtual method. Also requires a bit more work setting up 
the tree. Might be faster than 3), definitely smallest memory 
footprint. Relatively easy to follow.

There may be other options, but from the above I'd go with either 
1) or 4).

Now, I've noticed that X doesn't have a pointer to its parent, so 
traversing the tree to find the root is currently impossible. If 
this is true, and you have no other use for traversing up the 
tree, then 1) is the way to go, as 2) is almost never a better 
option, and 3) and 4) requires adding a parent pointer so you'll 
pay the memory price anyway.

--
   Simen


More information about the Digitalmars-d-learn mailing list