Sure. It's of course possible to get the same effects in OO programming as with old-school procedural programming. But, there is a huge inertia and intuitive pressure with OO (and C++ in particular) to use the STL, etc. Everything people are taught wrt OO will lead a person to think as follows:
Quote:
Hmm, I need a list of enemies in my game. Well, I'll make a kind of generic list which doesn't care what' in it. And, my enemies... they have no real need that I can think of to know that they're part of the list... etc.
It does make sense to the extent that the only real reason the enemies would need to know they are part of a list is for the sake of efficiency -- there is no *logical* reason they should know, given an infinitely fast CPU.
The problem I see with OO is that it takes the (generally good) idea that abstraction and APIs and black boxes are good to an extreme, and makes it kind of the "default" way of thinking about everything, even at the lowest levels, and you often find that there are unintended consequences. Much of the "refactoring" that is so popular and has become such a natural part of the development process is, I think, aimed at fixing these overly encapsulated interfaces which have led, unconsciously, and unforeseably in many cases to an inefficient design.
Of course I do think that profiling is an invaluable tool -- (and BTW... profiling a heavily STL using program is a real eye-opener if you haven't tried it, and if you can decipher the horrendous output). Premature optimization is the root of all evil or some such, it has been said.
As for "At some point, somewhere in there, you need to determine the /* oh, I'm dead */. " Yes, you do. But it doesn't have to be per-object. It can be in the code that detects, say, a laser beam intersecting a bad guy -- that is, it can be limited to comparisons between the laser beam's location and the subset of bad guys near the laser (as determined by the fact that the list is, say, sorted into zones) and the fact that the bad guys are on a "rarget list" which is not as big as the complete object list. Likewise, for objects which have a limited lifetime (e.g. say, sparks, they live say, 30 frames or so, then die. When they die -- which they notice while they're moving themselves -- they just remove themselves from the list.)
The difference is that you check these things when the associated objects are already doing something else, already sitting in the CPu's cache, and not in a separate step that's global to all objects.
Amd of upi DID have the separate global check, the very same tests I already described above would have to be done IN ADDITION, just to set the flag that the global check is doing. So -- 50000 comparisons are indeed eliminated, because your solution looks like this:
/* oh, I'm dead */ dead = true;
and elsewhere:
for each object if it's dead, jim, kill it with fire.
You essentially do the check *twice*. Which is my complaint.