SyntaxStudy
Sign Up
C++ Dynamic Allocation: new, delete, and Placement new
C++ Beginner 1 min read

Dynamic Allocation: new, delete, and Placement new

The 'new' operator allocates memory from the heap and invokes the object's constructor; 'delete' invokes the destructor and then frees the memory. For arrays, 'new[]' and 'delete[]' must be used as a matched pair — mixing them with the scalar forms is undefined behaviour. 'std::nothrow' variants return 'nullptr' instead of throwing 'std::bad_alloc' on allocation failure. Placement new constructs an object at a pre-allocated memory address without allocating new memory. This technique is used in custom memory allocators, memory pools, and certain embedded systems where heap allocation is forbidden. The object must be explicitly destroyed by calling its destructor directly — 'obj->~Type()' — because 'delete' would also try to free memory that was not allocated by the default allocator. Memory alignment is an important consideration for performance and correctness. Misaligned access to SIMD types or atomic variables can cause hardware faults on some architectures. C++11 introduced 'alignas' to specify alignment requirements and 'alignof' to query them. 'std::aligned_storage' and 'std::aligned_alloc' provide aligned memory blocks for advanced use cases.
Example
#include <iostream>
#include <new>       // std::nothrow, placement new
#include <cstdlib>   // std::malloc, std::free

struct Widget {
    Widget(int id) : id_(id) {
        std::cout << "Widget(" << id_ << ") constructed\n";
    }
    ~Widget() {
        std::cout << "Widget(" << id_ << ") destroyed\n";
    }
    int id_;
};

int main() {
    // Scalar new/delete
    Widget* w = new Widget(1);
    delete w;

    // Array new/delete
    Widget* arr = new Widget[3]{2, 3, 4};
    delete[] arr;   // must use delete[], not delete

    // nothrow: returns nullptr instead of throwing
    Widget* big = new (std::nothrow) Widget(5);
    if (!big) {
        std::cout << "Allocation failed\n";
    } else {
        delete big;
    }

    // Placement new: construct into pre-allocated buffer
    alignas(Widget) unsigned char buf[sizeof(Widget)];
    Widget* pw = new (buf) Widget(99);   // no heap allocation
    std::cout << "Placed widget id: " << pw->id_ << "\n";
    pw->~Widget();   // explicit destructor — do NOT delete pw

    // Alignment query
    std::cout << "alignof(Widget) = " << alignof(Widget) << "\n";
    std::cout << "sizeof(Widget)  = " << sizeof(Widget)  << "\n";

    return 0;
}