Course · C++

What new and delete actually do

Jun 25, 20263 min

A free lesson from the course “C++ without Memory Allocations” on Stepik.

new and delete in C++

Although new and delete are often used as a replacement for C's malloc and free functions, they are not exact analogues of them. The main difference is that new automatically calls the object's constructor after allocating memory, while delete calls the destructor before freeing the memory. With malloc and free this does not happen: they work only with a raw block of memory.

In addition, in C++ you can overload the new and delete operators for your own classes. This makes it possible to use custom allocators, keep allocation statistics, or debug memory usage. Such flexibility makes new/delete far more powerful tools than the standard C functions.

What new and delete do

The standard new and delete expressions do not merely allocate and free memory. They also call the object's constructor when it is created and the destructor when it is deleted.

struct car {
    car();
    ~car();
};

void test()
{
    auto p = new car;
    delete p;
}

Here is what we get in assembly

test():
        push    r14
        push    rbx
        push    rax
        mov     edi, 1
        call    operator new(unsigned long)@PLT
        mov     rbx, rax
        mov     rdi, rax
        call    car::car()@PLT
        mov     rdi, rbx
        call    car::~car()@PLT
        mov     esi, 1
        mov     rdi, rbx
        add     rsp, 8
        pop     rbx
        pop     r14
        jmp     operator delete(void*, unsigned long)@PLT
        mov     r14, rax
        mov     esi, 1
        mov     rdi, rbx
        call    operator delete(void*, unsigned long)@PLT
        mov     rdi, r14
        call    _Unwind_Resume@PLT

DW.ref.__gxx_personality_v0:
        .quad   __gxx_personality_v0

Note that the new and delete expressions should not be confused with the operators themselves, which can be called as functions. In the example above, the new expression first calls the new operator to allocate memory, and then calls the object's constructor.

The following code demonstrates how these operators can be used to allocate and free raw memory:

struct car {
    car();
    ~car();
};

void test()
{
    auto raw_p = operator new (sizeof(car));
    operator delete (raw_p, sizeof(car));
}

And here is how it looks in assembly:

test():
        push    {r4, lr}
        mov     r0, #1
        bl      operator new(unsigned int)
        mov     r1, #1
        bl      operator delete(void*, unsigned int)
        pop     {r4, lr}
        bx      lr

We can overload these operators, which we will discuss later. But in fact, C++ has several different new and delete expressions that can be used in different situations.

Take the course on Stepik →

← All articles