C++ Memory Management: Dynamic Allocation, Smart Pointers, RAII & Best Practices

1. Memory Management

Q: What is memory management in C++?

Memory management in C++ involves allocating, using, and deallocating memory for variables and objects during program execution. It ensures efficient use of resources and prevents issues like memory leaks or undefined behavior, critical for robust applications.

Q: What are the types of memory allocation in C++?

Q: How do you allocate and deallocate dynamic memory in C++?

Syntax:

int* ptr = new int(10); // Allocate single int
int* arr = new int[5];  // Allocate array
delete ptr;             // Deallocate single int
delete[] arr;           // Deallocate array

Q: What is a memory leak, and how does it occur?

A memory leak occurs when dynamically allocated memory is not deallocated, causing the program to consume memory unnecessarily. It happens when pointers to allocated memory are lost (e.g., reassigned or go out of scope) without calling delete.

Q: Can you give an example of dynamic memory management in C++?

#include <iostream>
using namespace std;

class Resource {
private:
    int* data;
public:
    Resource(int value) {
        data = new int(value); // Dynamic allocation
        cout << "Allocated resource with value: " << *data << endl;
    }
    ~Resource() {
        delete data; // Deallocate
        cout << "Resource deallocated" << endl;
    }
    void display() const {
        cout << "Value: " << *data << endl;
    }
};

int main() {
    Resource* r = new Resource(42);
    r->display();
    delete r; // Calls destructor, deallocates memory
    
    int* arr = new int[3]{1, 2, 3};
    cout << "Array: " << arr[0] << ", " << arr[1] << ", " << arr[2] << endl;
    delete[] arr; // Deallocate array
    
    return 0;
}

Output:

Allocated resource with value: 42
Value: 42
Resource deallocated
Array: 1, 2, 3

Q: What are smart pointers in C++?

Smart pointers are classes (from <memory>, C++11) that manage dynamic memory automatically, preventing leaks by deallocating memory when no longer needed. Types include:

Q: Can you give an example of smart pointers in C++?

#include <iostream>
#include <memory>
using namespace std;

class Resource {
public:
    Resource(int v) : value(v) { cout << "Resource created: " << value << endl; }
    ~Resource() { cout << "Resource destroyed: " << value << endl; }
    void display() const { cout << "Value: " << value << endl; }
private:
    int value;
};

int main() {
    // unique_ptr
    unique_ptr<Resource> uPtr = make_unique<Resource>(10);
    uPtr->display();
    // Automatically deallocated when uPtr goes out of scope
    
    // shared_ptr
    shared_ptr<Resource> sPtr1 = make_shared<Resource>(20);
    {
        shared_ptr<Resource> sPtr2 = sPtr1; // Share ownership
        sPtr2->display();
        cout << "Reference count: " << sPtr1.use_count() << endl; // Output: 2
    } // sPtr2 destroyed, but sPtr1 still holds resource
    sPtr1->display();
    // Resource deallocated when sPtr1 goes out of scope
    
    return 0;
}

Output:

Resource created: 10
Value: 10
Resource destroyed: 10
Resource created: 20
Value: 20
Reference count: 2
Value: 20
Resource destroyed: 20

Q: What is RAII, and how does it relate to memory management?

Resource Acquisition Is Initialization (RAII) is a C++ idiom where resources (e.g., memory, files) are acquired during object creation (constructor) and released during destruction (destructor). It ensures automatic cleanup, reducing memory leaks. Smart pointers and file streams use RAII.

Q: What are memory management issues in C++?

Q: How does memory management differ from C?

Q: Can you give an example demonstrating a memory leak and its fix?

#include <iostream>
#include <memory>
using namespace std;

// Example with memory leak
void memoryLeak() {
    int* ptr = new int(100); // Allocated but not deleted
    cout << "Value: " << *ptr << endl;
} // Leak: ptr goes out of scope, memory not freed

// Fixed with smart pointer
void noMemoryLeak() {
    unique_ptr<int> ptr = make_unique<int>(100);
    cout << "Value: " << *ptr << endl;
} // ptr automatically deallocated

int main() {
    memoryLeak(); // Causes memory leak
    noMemoryLeak(); // No leak, thanks to unique_ptr
    return 0;
}

Output:

Value: 100
Value: 100

Q: What are best practices for memory management in C++?

Q: What is the role of destructors in memory management?

Destructors automatically clean up resources (e.g., dynamic memory) when an object goes out of scope or is deleted. They are key to RAII, ensuring resources are released without manual intervention. Example: See the Resource class destructor in the dynamic memory management example above.

Q: What are common mistakes in C++ memory management?