C++ requires one to manage heap memory. Memory management can be tedious and error-prone. If different things reference this memory, and you de-allocate the memory without someone knowing, bad things can happen. If you forget to de-allocate the memory, you have a memory leak.
One solution is to use smart pointers. They let a programmer use similar syntax as normal pointers, with the benefit of memory being automatically cleaned up when nothing references that memory.
What you’ve gained by using smart pointers:
- Anxiety reduction as you believe you are insulated from having to think about memory management
- Potentially less typing
What you’ve lost by using smart pointers:
- Stuff is now happening behind the scenes, but the syntax looks as though nothing is happening behind the scenes. Operators are overloaded. Evil is in the air!
- The timing of memory de-allocations is implicit. Hidden both in time and in the code.
Normally I’m fine with memory management being done behind the scenes. Our tools are written in C#, a language with a memory manager built in, and I could care less about memory. Tools can be memory hogs to a certain (certainly huge) extent.
However, our runtime game needs to care. I want the easiest, most transparent way to manage memory.
To ease memory management in C++ I do the following:
- Memory allocations using “new” are only allowed when a chunk (or level) of the game is loaded. Not frame to frame. Likewise, de-allocations are only allowed when a chunk (or level) of the game is unloaded.
- I use a naming convention for class attributes. An “m” prefix means member, an “mp” prefix means a member that is a pointer, and that the class is responsible for allocating and de-allocating its memory. Finally, I use “mpe” for member pointers for whose memory the class is responsible for neither allocating nor de-allocating. The “e” means external.
- I use simple macros to ease the typing related to allocation/de-allocation.
So, I centralize (in time) allocations and de-allocations, choose names that immediately identify a class’s responsibility, and wrap some of the clunkiness (such as checking for null before a de-allocation, setting to null after a de-allocation) in macros.
Some people use memory pools to achieve centralizing allocations and preventing a ton of frame-to-frame allocations. If I weren’t the only programmer on this project I would research this. As it stands my solution is easy to implement and transparent, and I can’t waste time researching “best” solutions to a problem that’s under control.