Курс · C++

Что делают new и delete

25 июня 20263 мин

Бесплатный урок из курса «С++ без аллокаций памяти» на Stepik.

new и delete в C++

Хотя new и delete часто используются как замена функций malloc и free из C, они не являются их точными аналогами. Основное отличие в том, что new автоматически вызывает конструктор объекта после выделения памяти, а deleteвызывает деструктор перед освобождением памяти. В случае с malloc и free этого не происходит: они работают только с сырым блоком памяти.

Кроме того, в C++ можно перегружать операторы new и delete для своих классов. Это даёт возможность использовать кастомные аллокаторы, вести статистику выделений или отлаживать работу с памятью. Такая гибкость делает new/delete гораздо более мощными инструментами, чем стандартные функции из C.

Что делают new и delete

Стандартные выражения new и delete не просто выделяют и освобождают память. Они также вызывают конструктор объекта при создании и деструктор при удалении.

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

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

Что получается в ассемблере

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

Обратите внимание, что выражения new и delete не следует путать с самими операторами, которые можно вызывать как функции. В приведённом примере выражение new сначала вызывает оператор new для выделения памяти, а затем вызывает конструктор объекта.

Следующий код демонстрирует, как с помощью этих операторов можно выделять и освобождать сырую память:

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

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

И как это выглядит в ассемблере:

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

Мы можем перегружать эти операторы, о чём мы поговорим позже. Но на самом деле в C++ существует несколько различных выражений new и delete, которые можно использовать в разных ситуациях.

Пройти курс на Stepik →

← Все статьи