I was wondering when should I allocate a class on the stack in C++? I have a strong background in Java and in Java all classes are allocated on the heap, using the new
Use automatic (stack) allocation whenever the function scope - or the scope of a control block such as a for
, while
, if
etc. inside the function - is a good match for the lifetime the object needs. That way, if the object owns/controls any resources, such as dynamically allocated memory, file handles etc. - they will be freed during the destructor call as that scope is left. (Not at some unpredictable later time when a garbage collector winds up).
Only use new
if there's a clear need, such as:
needing the object to live longer than the function scope,
to hand over ownership to some other code
to have a container of pointers to base classes that you can then process polymorphically (i.e. using virtual dispatch to derived-class function implementations), or
an especially large allocation that would eat up much of the stack (your OS/process will have "negotiated" a limit, usually in the 1-8+ megabyte range)
std::unique_ptr<>
to manage the dynamic memory, and ensure it is released no matter how you leave the scope: by return
, throw
, break
etc.. (You may also use a std::unique_ptr<>
data member in a class
/struct
to manage any memory the object owns.)Mathieu Van Nevel comments below about C++11 move semantics - the relevance is that if you have a small management object on the stack that controls a large amount of dynamically allocated (heap) memory, move semantics grant extra assurances and fine-grained control of when the management object hands over its resources to another management object owned by other code (often the caller, but potentially some other container/register of objects). This handover can avoid data on the heap being copied/duplicated even momentarily. Additionally, elision and return-value-optimisation often allow nominally automatic/stack-hosted variables to be constructed directly in some memory they're eventually being assigned/returned-to, rather than copied there later.
In large codebase we use stack allocation for simple struct objects while for more complex classes(that involve polymorphism, memory ownership etc) we always use dynamic allocation.