Alright, so I'm sure this question has been asked a million times, but I was wondering about the "new" keyword. I get that it allocates new memory space or whatever, but what would I use it for? I'm trying to get into game dev, and I heard that could be really helpful.
Normally, you'd create an object on the stack. But when it comes to large structures (relative to stack size), the stack may only handle a few of these large objects, and therefore, must be placed in the heap to prevent stack overflows.
In commercial games, 1 large pool of memory is allocated. This pool is used to store resources such as containers, geometry, et cetera. If you used the stack, you'd run into a stack overflow pretty quickly. This technique prevents a few things (as far as I know of):
• Fragmentation. Excessive calls to new() can fragment memory. Fragmented memory wastes memory, even if it isn't in use.
• Efficiency. When an object needs to be dynamically allocated, the memory is already reserved, and needs not wait for the memory to become available. The only overhead is the constructor call, and what happens inside the constructor.
• Safer. Only 1 well-placed call to delete() can release the entire pool. If you used multiple calls to new(), you'd have to call delete() multiple times, too, which can cause you to lose track.
The only downside to this approach is the potential for misaligned data is much higher. If two objects are misaligned, the CPU has to waste more time fetching the data it needs to finish what it started.
Allocated objects have the advantage over stack objects, because unlike stack objects, allocated objects can be destroyed in any order, whereas stack objects have to be destroyed in reverse order. Always.
The only downside to this approach is the potential for misaligned data is much higher
That's not the only downside. You're making memory pools sound like they're some kind of magic bullet. They're anything but.
- It's more complicated. Ever tried writing an efficient memory pool system? It can get pretty hairy. Though granted you can probably just grab an existing lib for a good memory pool implementation so this isn't so much of an issue.
- It doesn't prevent you from having to clean up. Just because a single delete will wipe out the entire memory pool doesn't mean you can forget to clean up individual objects. Failure to delete items will still leak -- they'll consume more and more of your memory pool causing you to either have to allocate more pools over time (defeating the point of having a memory pool)... or worse, just running out of space and having allocations fail.
Cleaning up the entire pool at once is more efficient than going through and cleaning up each individual element (although the pool will still have to go through and call dtors for each individual object) -- but how often do you delete the whole pool? If you are using one massive pool for the whole program, I'm thinking you'll do that exactly once: when the program shuts down.
- It doesn't prevent fragmentation. Memory pools get fragmented just like the heap does.
Having one large memory pool that every allocation in your program draws from kind of defeats the entire point of using a memory pool. If you're doing that, there really are few/no advantages to using one over just using the heap directly.
Memory pools are best when you will be doing a lot of small, short-life allocations. And when the number of different types of objects the pool has to accommodate are limited (ie: having a separate pool for Foos and for Bars might be more practical, since the Foo pool can have block sizes of sizeof(Foo), reducing allocation/fragmentation concerns).