The problem as I see it is by having a Release() method, you are then implying that instances of your class can exist in two states - formed and released. After you call Release(), your object is still around and can still be operated upon, so your internals of the class and your users then need to code around this, checking the state of the object during any operations.
One of the strongest principles of encapsulation is class invariants - if I have a std::string object, I am guaranteed from the outside to have an object containing a valid string or the empty string. I don't have to check isValid() every time.
No, that isn't what I am saying at all.
You want something that can be created almost instantly. Think of it as an empty string, or an empty vector, or an empty hash table. That doesn't mean it is ill-formed, that doesn't mean it is invalid, that doesn't mean RAII doesn't apply. It is well-formed and complete. It just means it is currently empty.
Consider the ever-popular epic work, the GameObject class. It serves as the base class of everything scriptable and a game world can have tens of thousands or even hundreds of thousands of them. A continuous world might have many million game objects in it.
Usually this thing grows to be MASSIVE. It isn't just a single transformation with position and orientation. It is usually hooked up to lots of components. it can be associated with models and textures and animations and shaders. It can be visible to the player, or not. It can be active and alive and important to the player, or it can be on the other side of the game universe just sitting around waiting for the player to walk across the map. Each child class can add their own details and containers and resource needs. It gets connected and disconnected to systems everywhere in the game.
When you start up the game you generally don't want every game object to load every detail immediately when it is constructed. For a large game the process could take five, ten or twenty minutes. For a continuous world game, you could easily exhaust all your memory.
When I say "Give me an array of 50 game objects", the absolute last thing I want to have happen is to cascade into 50 meshes loading, 50-300 textures loading, 500+ animations loading, 30+ shaders loading, tons of audio loading, followed by objects self-registering inside the world and the spatial trees, appending themselves to the render lists, including itself in the pathfinder, and so on. Such a process might mean thousands of calls to the disk as file names are turned into data streams and each stream individually pulled from a slow-spinning platter, followed by hundreds of calls into some of the most expensive systems of the game. No! I want 50 completely empty game objects that I can use for my own purposes immediately.
The key detail is that you don't do all of those things during construction and destruction. Instead, you do it at a time that you can control, a time that is appropriate. You can replace the very expensive models and textures and animations with simple proxies when they are off screen; they can be reloaded in moments when the player approaches them. You can remove proximity checks when the player is on the other side of the world, the land mine won't be stepped on when the player is on the other side of the world.
I am not saying to not initialize your objects. Far from it. Everything should be in a valid state. What I am saying is that "valid state" does not mean "requires 47MB of resources", but can also mean "empty", "ready for delayed loading", "proxied", and potentially much more. Careful resource management is very important in games.
Edited by frob, 18 February 2014 - 03:29 AM.