std.container and classes

Jonathan M Davis jmdavisProg at gmx.com
Sun Dec 18 20:12:57 PST 2011


On Sunday, December 18, 2011 02:46:01 Andrei Alexandrescu wrote:
> If this is a new notion, it might take a while for all of its aspects to
> sink in. I'm not saying that to be smug - reference counting vs. other
> methods of collecting garbage is definitely a difficult topic on today's
> architectures, and I can say at least it took me quite a while to build
> some reasonable mental model of the related tradeoffs.

After thinking about this a bit, I don't think that custom allocators are 
really going to work with classes very well. Unless you allocate the entire 
class with the custom allocator (as opposed to just telling the container to 
use the custom allocator), the memory won't be cleaned up until the object is 
collected by the GC (even though it's using a custom allocator to allocate its 
internals), in which case, what does the custom allocator really buy us? So, 
the idea of just passing the allocator to the container doesn't seem to cut it 
for a class. The object itself needs to be allocated with the custom 
allocator. On top of that, if you're allocating the container with a custom 
allocator, doesn't that risk issues like what the to-be-deprecated scope 
modifier causes? You practically end up having to wrap the class in a struct 
anyway, in which case, what's the point of using a class?

Just in general, it's much harder to control the memory if the container is a 
class rather than a struct. With a struct, you can do pretty much whatever you 
want with the memory. Its lifetime is strictly controlled, which gives much 
greater opportunites to optimize its memory usage. With a class, it's going to 
be difficult to completely divorce the container from the GC in a clean manner.

With a struct, we could easily make the default not use the GC at all, which 
would make the default use of the containers much more efficient. You also 
wouldn't have to worry about creating the container itself with an allocator 
and all of the potential issues that that brings.

I don't particularly like the idea of the cost of passing the container around 
as a struct (since it's few member variables will have to be memcopied and the 
ref-counting will have to be done), but that's not a huge cost (though it _is_ 
a pervasive one), and I'm begginning to think that it's a necessary one if we 
want containers to be able to properly and efficiently manage their own memory. 
Depending on the use case, the benefits from the containers being able to fully 
manage their own memory without the programmer having to do anything special 
could easily outweigh the additional cost of passing a struct around. And if 
ranges over such containers are passed around more frequently than the 
containers themselves (as I would expect), then the minor cost of passing the 
container around is even less of a big deal, since it would primarily be the 
ranges being passed around.

So, I'm beginning to think that we're going to have to go the struct route.

- Jonathan M Davis


More information about the Digitalmars-d mailing list