Ugrás a tartalomhoz

Szerkesztő:LinguisticMystic/cpp/StackHeapOOP

A Wikiszótárból, a nyitott szótárból

Stack vs Heap in C++ and OOP

[szerkesztés]

In C++, every program utilizes two primary types of memory for storing data: the stack and the heap. These memory areas differ in terms of lifetime, allocation method, performance, and risk of errors like memory leaks or overflows.

Understanding these differences is especially critical in Object-Oriented Programming (OOP), where objects can be dynamically created and destroyed. Knowing when and how to use stack or heap memory helps you write efficient and safe C++ programs.



🧠 Heap and Stack – The Basics

[szerkesztés]

🔁 The Stack

[szerkesztés]
  • The stack is a fast, managed memory region.
  • Memory is automatically allocated and deallocated when functions are called or return.
  • It follows the LIFO (Last In, First Out) principle.
  • Stack memory is limited in size (usually a few MB), so allocating large structures may cause a stack overflow.
  • Ideal for temporary/local variables and short-lived objects.

🌐 The Heap

[szerkesztés]
  • The heap is a large pool of memory for dynamic allocation.
  • You must manually allocate and deallocate memory using new and delete.
  • If you forget to deallocate, you create a memory leak.
  • It’s more flexible and scalable for large or long-lived objects, especially when their size or count is not known at compile-time.



🔍 Example: Stack vs Heap Allocation

[szerkesztés]
int main() {
    int stackVar = 10;                    // allocated on the stack
    int* heapVar = new int(20);           // allocated on the heap
    delete heapVar;                       // manually deallocated
    return 0;
}
  • stackVar is a local variable. It is automatically destroyed when main() ends.
  • heapVar points to dynamically allocated memory. You must call delete to free it.



⚠️ Common Pitfalls

[szerkesztés]
void pitfalls() {
    int* memLeak = new int[100];       // ❌ memory leak (no delete)
    int stackOverflow[1000000];        // ❌ stack overflow (too large)
}
  • memLeak: Memory allocated with new[] is never freed.
  • stackOverflow: Allocating large arrays on the stack can crash your program.



✅ Best Practices

[szerkesztés]
  • Use the stack by default – it’s safer and faster.
  • Use the heap:
    • for large objects,
    • for unknown object lifetimes,
    • when you need the object to persist outside its current scope.
  • Always use delete or delete[] for heap memory – or better, use smart pointers.



🔐 Smart Pointers – Modern Memory Safety

[szerkesztés]

Smart pointers, introduced in C++11, manage heap memory automatically:

#include <memory>

void smartPointer() {
    std::unique_ptr<int> smart(new int(10));  // no need to manually delete
}

When smart goes out of scope, its destructor automatically deletes the pointed object.



🧱 OOP and Memory Allocation

[szerkesztés]

In OOP, the memory decision depends on how long you want the object to exist.

📦 Stack-based Object

[szerkesztés]
Employee martin("Martin Suvorov", 30);  // on the stack
martin.display();

When the function exits, the object is automatically destroyed.

🧊 Heap-based Object

[szerkesztés]
Employee* mPtr = new Employee("Martin Suvorov", 25);  // on the heap
mPtr->display();
delete mPtr;  // must manually deallocate

Heap-based objects persist beyond the function scope and must be manually managed.

Use -> when accessing members through a pointer. Use . for direct stack objects.


🏢 Example: Company with Dynamic Employees

[szerkesztés]

When you don’t know the number of employees beforehand, heap allocation is a better choice:

class Company {
private:
    std::vector<Employee*> employees;

public:
    void addEmployee(const std::string& name, int age) {
        employees.push_back(new Employee(name, age));  // heap allocation
    }

    void displayEmployees() {
        for (Employee* e : employees)
            e->display();
    }

    ~Company() {
        for (Employee* e : employees)
            delete e;  // free all heap-allocated memory
    }
};
int main() {
    Company myCompany;
    myCompany.addEmployee("John Doe", 30);
    myCompany.addEmployee("Jane Smith", 25);
    myCompany.displayEmployees();
    return 0;
}
  • Company is on the stack.
  • Each Employee is created on the heap.
  • The Company class uses a destructor to avoid memory leaks.



🔁 Lifetime and Scope

[szerkesztés]
  • Stack object → automatically destroyed at end of scope.
  • Heap object → lives until explicitly deleted or managed by a smart pointer.
  • Destructor → automatically invoked when:
    • a stack object goes out of scope,
    • a heap object is deleted,
    • or a smart pointer releases the object.



📌 Final Best Practices Summary

[szerkesztés]
Situation Recommendation
Small, short-lived object Use stack
Large object or collection Use heap
Unknown lifetime or size at compile time Use heap
Want automatic memory management Use smart pointers
Object must outlive function scope Use heap or return by pointer
You’re managing dynamic collections Use std::vector, smart pointers



🧠 Conclusion

[szerkesztés]

Memory management in C++ is powerful but requires discipline:

  • Understand stack vs heap trade-offs.
  • Use the stack by default when possible.
  • Use the heap for flexibility but manage memory carefully.
  • Prefer smart pointers over raw pointers to reduce human error.
  • Always define destructors when your class owns heap memory.

By mastering memory handling in OOP, you gain the ability to write robust, efficient, and leak-free programs in C++.