@SeanMiddleditch:
That would surprise me. There should be very, very little architecture-dependent code in any sane codebase - even performance-sensitive game engines - these days. You may still have a lot of platform-specific code, but that should at least be pushed out into leaf libraries (your audio library, renderer, etc.).
Eh, nobody said my codebase was sane ;)
Joke aside, I probably did overexaggerate a bit, but I have at least a few places in mind where I (ab)use the fact the MSVC has no strict aliasing, and I don't even want to talk about 32 vs. 64 bit type size stuff (damn, at least thats something I'll have to look at sometimes soon...).
Maybe, maybe not. That really depends on how you're accessing them. If you're iterating over them linearly then not really; if you're accessing them randomly then it certainly can. You don't just want to align everything to the cachline size, though; you want the object to evenly fit in the cacheline and then ensure that your backing store is cacheline aligned. e.g., if you're allocating small 8 byte structures, you can fit eight of those in a single cacheline (on typical x86 architectures). You thus don't want to align them to the cacheline, you just want to make sure that they are evenly divisible into a cacheline.
Well ok, since I'm mostly iterating in a semi-linear fashion in the places where performance matters (with mostly linear I mean iterating via sort of an ordered indirection table with some holes), based on your explanation I think I don't need to align that way then. Specially since I'm not using multithreading yet.
Of course, depending on the data in question, this really doesn't even matter. Some game developers fetishize performance to the detriment of their game as a whole. :)
I wouldn't totally count me to that list, but I certainly favour engine design over game design now. Also I'm doing this optimization of my ECS-framework as part of an university assignment. We were told to choose a certain piece of software and optimized it, so figured since I had this in the back of my mind, might as well do it - and even if it doesn't matter currently whether my 2D game runs in 2300 or 3000 FPS, at least the assignment gives me a good excuse to generate some higher, or lower numbers (in frametime) ;)
That is a general problem with C++. As you know, you just have to call your parents' operator= in the child's operator=.
Funny, I somehow never realized that until now. Might be because I generally tend to use inheritance and explicit operator= sparcely, but I know this bit me in the ass at some places with copy-ctors. Come to think of it, I just fixed a certain bug yesterday due to me forgetting to call a parents copy-ctor in some class.
Of course, even better is to just not write custom move operators - the auto-generated ones should do everything you need automatically, including invoking parents' operators. If you use RAII-style ownership for everything then you can usually follow the Rule of Zero.
I agree with you, problem was that MSVC only recently adopted auto-generated move-constructors - I'm not even talking about "Class(Class&&) = default;", but before that you had to declare an explicit move constructor just for them to get generated (at least I belive this was the case), so I ended up writing a whole f***ton of simple move ctors, and I'm still in the process of setting them all to "default".
On problem I see though is that default-move-ctors will not properly move PoD values like integers, which means that sometimes classes will be left in an invalid state. Not so much a problem for containers, in fact I'm not sure how much of a problem that actually is. I decided to keep some explicit move-ctors specifically due to this, but I might need to evaluate it again.
It can totally be mitigated, just not with raw pointers. Store a smart pointer that knows how to use an indirection table, which is exactly what component/entity ids end up doing for you anyway. :)
Why yes, I'm already doing that, what I meant is that it cannot be done with raw pointers.
I have an "EntityHandle" class that keeps an unique id as well as a pointer to the entity container, and than does a lookup int he entity storage (since due to the layout of this I can find any entitiy in mostly a few iterations of a linear search). But the idea is exactly this, I use this class for long-lasting access, eigther to store a reference to an entity or when a certain part of the code that is iterating over a bunch of entities could potentially modify the entity container meanwhile (think script calls). Since I'm already doing a delayed deletion of entities, I'm thinking about delaying creation of entities too (or at least insertion to the container), so that I can completly skip this step as well. But thats a different topic, just had that on my mind.
That being said I don't have such a system for components because I didn't need it yet. Component access is currently via the actual entity, and in my ongoing work to optimize the system I'm in the process of caching all components for an iteration-cycle in a specified structure, which will always be updated accordingly. Don't know, maybe I'll need such a specified "smart pointer" for components at some point, but for now doesn't look like it.
@JohnnyCode:
Of course, the fact of linked list, though of very small structures, is a certain performance hit, but it provides this measure to safely use and access your objects even if they get moved by managing vector.
Hm, I see what you mean, but as you see above I already have structure in place that take care of this, just that they take no performance hit where "unsafe" access can actually be done safely (uh, that sounds right). And since I'm currently in the process of optimizing heavly for performance, I don't think I'll do that yet, but I'll keep it in the back of my head if there ever comes a need.