Skip to main content
GameDev.net gamedev.net
🔒 Locked

C++ - Putting the entire game instance in a heap object?

Started by ichitaraaa Jun 29, 2025 at 6:09 AM 11 replies 4.8k views
Original Post
ichitaraaa
ichitaraaa

Is it okay to put the entire game instance into an object on the heap in C++? Like this:

int main()
{
    GameInstance* inst = new GameInstance;
    GameInstance->Run()
    delete GameInstance;
    
    return 0;
}

I’ve seen this done about twice now but I’m not sure if it’s a good practice, good idea or how it’s usually done for a robust or production scenario.

All8Up
All8Up

@ichitaraaa There is no particular reason not to do such a thing. It has no impact on performance, there is of course a new/delete involved but that is done once so it doesn't matter, etc. The benefit of such a thing is being more modular. You can bring up an instance from main/winmain/services/daemons etc without having to rework any code contained in ‘main’ itself. Additionally, such a pattern gives you benefits in some cases such as being able to bring up multiple instances in the same process, say for instance bringing up multiple test bots to run around in a MMO server for stress test reasons. Or, getting crazy, you could go down the road of having worlds within worlds. For instance, a game (Cosmoteer?) runs an outer “world” game instance and each ship is its own instance that simulates the crew. (I don't know that they actually “do” that, just that it could work that way.) So, I'd rephrase the question as: “Why wouldn't you?”…

TooOld2rock-nRoll
TooOld2rock-nRoll

Well….

In an age where we already have so much resources you don't have to really care, it is almost a a matter of aesthetics, but it would be a big deal in a more constrained environment.

I mean, there is no free lunch, you make your executable larger or you take longer to load everything when you need it. Depends on what is more important for the target you are developing for.

Anyway, using opengl, you can´t really do anything (not even load basic resources) before having a window handler and the bindings to the opengl API, so it made more sense to my “start up” game instance to be declared at the beginning of main() and free the game procedures from worrying about what is available at any given time.

"No, you're never too old to rock and roll
If you're too young to die"
frob
frob

Sure, it's fine. It is typical to do more, but it works.

The code allocates an arbitrary object, runs the constructor, calls a function, destroys the object, and frees the space.

You might as well name the function “main”, as it is basically the same as a wrapper for the program's main function.

RmbRT
RmbRT

Depending on how large the game is, you NEED to put it on the heap, because the stack might not be able to contain it (for example if it has large fixed-size buffers/arrays). Especially for something that lives as long as main(), there is no reason why you shouldn't put it on the heap. It makes 0 difference otherwise. malloc() is not that slow that you would even be able to notice a call to it. Maybe a few microseconds or something. And inside the game, you will have many more malloc() calls, anyway. And the memory overhead of a single allocation is also negligible, as far as I am aware.

Walk with God.
littlememelord
littlememelord

@ichitaraaa

// 1. Allocate GameInstance on the heap
GameInstance* inst = new GameInstance();

// 2. Call a member function through the pointer
inst->Run();

// 3. Deallocate GameInstance from the heap
delete inst;

Operating systems are smart. They lazily load memory only when it's needed. It's completely normal to have to put stuff on the heap on a regular basis.

When you put an object on the heap, you are requesting the operating system for enough memory for Gameinstance. The operating starts by giving it virtual address spaces. Virtual meaning it's in a page table - not physical memory from RAM yet. The page table loads pointers to real memory *only when its needed*.

so let's say inside your GameInstance() constructor function you:

//if you do nothing it is in fact still allocated in virtual memory

if you say

this->inst->numCharacters++

then you are instantiating a read or write - which triggers a page fault. You are demonstrating real use of the memory. Therefore the page table will adjust its page table entry to point to physical memory, since it's needed.

Operating systems and compilers are optimized to handle a lot of heavy operations - but the key thing here is just cleanup. Go crazy - you have to usually put most of your stuff on the heap regardless.

RmbRT
RmbRT

On linux, more than 8MiB of data on the stack will crash your program. You are FORCED to use the heap for almost everything that's not just a few numbers or something.

Walk with God.
eCode7g
eCode7g

It's technically okay, but not recommended in most modern C++

Better option (below) because safe (automatically cleaned up), and more efficient (no heap overhead):

int main()
{
    GameInstance inst;
    inst.Run();
    return 0;
}

Btw, if for some reason you want to use the heap (e.g. polymorphism):

int main()
{
    std::unique_ptr<GameInstance> inst = std::make_unique<GameInstance>();
    inst->Run();
    return 0;
}

Still RAII safe, no memory leak risk.

Our gaming project:- geometry dash
taby
taby

Some times you just need to run the code after OpenGL initialization, thus using a heap-based object can ensure that your object's code runs after GLEW is initialized, etc. Use make_unique like in the above post.

Alberth
Alberth

eCode7g said:
no memory leak risk

You know it's VERY hard to have a memory leak in a terminated program, right?

TooOld2rock-nRoll
TooOld2rock-nRoll

Alberth said:

You know it's VERY hard to have a memory leak in a terminated program, right?

Alberth, my man, why would you start a pointer war????? lol

"No, you're never too old to rock and roll
If you're too young to die"
RmbRT
RmbRT

lol, this is when weird mental models stop considering the actual facts. You don't need to free pointers to memory allocations that live until exit. The only thing I can think of is if you have a destructor in the game object that definitely needs to be called. But the only thing that the OS doesn't really clean up on termination is something like filesystem-based mutexes. This reminds me of how rust wants to be safe, but reduces safety down to memory management and array bounds checks.

Rules of thumb are not laws, and only general suggestions for frequently occurring scenarios. Insisting on a rule of thumb where it doesn't belong just means you probably don't understand what you're doing. Reminds me of automated code linters. If you program against a theory, and not against a concrete real-world situation with real-world constraints and properties and guarantees, you're usually just making the computer go through unnecessary hoops for everything.

Walk with God.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.