← Назад к вопросам

Чем отличается malloc от new в C++?

1.0 Junior🔥 282 комментариев
#Язык C++

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Чем отличается malloc от new в C++?

malloc и new — это два разных способа динамического выделения памяти. Хотя оба выделяют память в heap, они работают по-разному и предназначены для разных целей.

Основные различия

Параметрmallocnew
ТипФункция CОператор C++
Заголовок<cstdlib>встроено в язык
Возвращаемое значениеvoid*Типизированный указатель
КонструкторыНЕ вызываетВызывает
ДеструкторыНЕ вызывает (free)Вызывает (delete)
ИнициализацияНетЕсть (в скобках)
Обработка ошибокВозвращает NULLВыбрасывает исключение
Пользовательская аллокацияНет (только в C++11+)Можно перегрузить
Memory pool / ArenaСложноЛегко (placement new)

1. malloc — выделение памяти без инициализации

malloc — это функция из C, которая просто выделяет блок памяти в heap и возвращает указатель на него. Она не вызывает конструкторы и не инициализирует объекты.

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

class MyClass {
private:
    int value;
    
public:
    MyClass() { 
        cout << "Constructor called" << endl; 
        value = 42;
    }
    ~MyClass() { cout << "Destructor called" << endl; }
};

int main() {
    // malloc НЕ вызывает конструктор
    MyClass* ptr1 = (MyClass*)malloc(sizeof(MyClass));
    // ptr1->value не инициализирован!
    // Деструктор НЕ будет вызван
    free(ptr1);
    
    cout << "---" << endl;
    
    // new ВЫЗЫВАЕТ конструктор
    MyClass* ptr2 = new MyClass();
    // ptr2->value == 42 (инициализирован в конструкторе)
    // Деструктор БУДЕТ вызван
    delete ptr2;
    
    return 0;
}

/* Вывод:
---
Constructor called
Destructor called
*/

2. new — полная инициализация объекта

new — это оператор C++, который:

  1. Выделяет память
  2. Вызывает конструктор (инициализирует объект)
  3. Возвращает типизированный указатель
class Point {
public:
    int x, y;
    
    Point() { 
        cout << "Default constructor" << endl; 
        x = 0; y = 0; 
    }
    
    Point(int x, int y) : x(x), y(y) { 
        cout << "Constructor(" << x << ", " << y << ")" << endl; 
    }
    
    ~Point() { cout << "Destructor" << endl; }
};

int main() {
    // new с параметрами конструктора
    Point* p1 = new Point(3, 4);
    cout << "p1 coordinates: (" << p1->x << ", " << p1->y << ")" << endl;
    
    // new с инициализацией (C++11)
    Point* p2 = new Point{5, 6};
    
    delete p1;
    delete p2;
    
    return 0;
}

/* Вывод:
Constructor(3, 4)
p1 coordinates: (3, 4)
Constructor(5, 6)
Destructor
Destructor
*/

3. Обработка ошибок

malloc возвращает NULL:

int* arr = (int*)malloc(sizeof(int) * 1000000000);
if (arr == nullptr) {
    cout << "Memory allocation failed" << endl;
}
free(arr);

new выбрасывает исключение (по умолчанию):

try {
    int* arr = new int[1000000000];  // Может выбросить std::bad_alloc
} catch (const bad_alloc& e) {
    cout << "Memory allocation failed: " << e.what() << endl;
}

4. Типизация

malloc требует приведения типа:

MyClass* ptr = (MyClass*)malloc(sizeof(MyClass));
// Опасно! Если размер неправильный, в runtime ошибка

new типизирован:

MyClass* ptr = new MyClass();
// Компилятор гарантирует правильный размер

5. Массивы

malloc не знает о массивах:

// malloc: просто выделяем память
MyClass* arr = (MyClass*)malloc(10 * sizeof(MyClass));
// Конструкторы НЕ вызваны!
free(arr);  // Деструкторы НЕ вызваны!

new[] управляет массивами:

// new[]: выделяет память + вызывает конструкторы
MyClass* arr = new MyClass[10];
// Все 10 конструкторов вызваны
delete[] arr;  // Все 10 деструкторов вызваны

6. Практическое сравнение

Сценарий: простой структурированный тип

#include <cstring>
using namespace std;

struct Point {
    int x, y;
};

int main() {
    // C стиль: malloc подходит
    Point* p1 = (Point*)malloc(sizeof(Point));
    p1->x = 10;
    p1->y = 20;
    free(p1);
    
    // C++ стиль: new лучше
    Point* p2 = new Point{10, 20};
    delete p2;
    
    return 0;
}

Сценарий: класс с конструктором

class FileBuffer {
private:
    char* buffer;
    int size;
    
public:
    FileBuffer(int size) : size(size) {
        buffer = (char*)malloc(size);
        cout << "FileBuffer created, size=" << size << endl;
    }
    
    ~FileBuffer() {
        free(buffer);
        cout << "FileBuffer destroyed" << endl;
    }
};

int main() {
    // ❌ НЕПРАВИЛЬНО: malloc не вызовет конструктор
    FileBuffer* fb1 = (FileBuffer*)malloc(sizeof(FileBuffer));
    // buffer указывает на garbage!
    free(fb1);
    
    cout << "---" << endl;
    
    // ✅ ПРАВИЛЬНО: new вызовет конструктор
    FileBuffer* fb2 = new FileBuffer(1024);
    delete fb2;
    
    return 0;
}

/* Вывод:
---
FileBuffer created, size=1024
FileBuffer destroyed
*/

7. Перегрузка new и delete

Одна из мощных особенностей new — это возможность перегрузки:

#include <iostream>
using namespace std;

class MyClass {
public:
    void* operator new(size_t size) {
        cout << "Custom allocator: " << size << " bytes" << endl;
        return malloc(size);
    }
    
    void operator delete(void* ptr) {
        cout << "Custom deallocator" << endl;
        free(ptr);
    }
};

int main() {
    MyClass* obj = new MyClass();
    delete obj;
    return 0;
}

/* Вывод:
Custom allocator: size bytes
Custom deallocator
*/

8. Placement new

Placement new позволяет выделить объект в заранее выделенной памяти. Это используется для специальных алокаторов:

#include <new>
using namespace std;

int main() {
    // Выделяем память
    char buffer[sizeof(MyClass)];
    
    // Создаём объект ВСредине выделенной памяти
    MyClass* obj = new (buffer) MyClass();
    
    // Вызываем деструктор явно (delete не будет вызван)
    obj->~MyClass();
    
    return 0;
}

9. Модернизация: smart pointers

В современном C++ рекомендуется использовать smart pointers вместо raw new/delete:

#include <memory>
using namespace std;

int main() {
    // ❌ СТАРЫЙ СТИЛЬ
    MyClass* raw = new MyClass();
    delete raw;
    
    // ✅ СОВРЕМЕННЫЙ C++
    unique_ptr<MyClass> ptr1(new MyClass());
    auto ptr2 = make_unique<MyClass>();  // Лучше
    
    shared_ptr<MyClass> ptr3 = make_shared<MyClass>();
    
    // Деструкторы вызовутся автоматически!
    return 0;
}

10. Когда использовать что?

Используй malloc, если:

  • Работаешь с C кодом
  • Типы не имеют конструкторов (простые структуры)
  • Нужна совместимость с C

Используй new, если:

  • Пишешь на C++
  • Работаешь с классами и конструкторами
  • Нужна типизация и обработка ошибок

Используй smart pointers (new через make_unique/make_shared), если:

  • Современный C++ (C++11 и выше)
  • Нужна автоматическая очистка памяти
  • Нужна exception safety

Чеклист правильного использования

  1. new требует delete (и new[] требует delete[])
  2. malloc требует free
  3. Не миксь new/delete с malloc/free
  4. Для классов с конструкторами — только new
  5. Рассмотри smart pointers для автоматического управления
  6. Убедись в exception safety при использовании new

Вывод:

  • malloc — функция C для выделения памяти, без вызова конструкторов
  • new — оператор C++ для выделения памяти с вызовом конструкторов

Для современного C++ разработчика рекомендуется избегать raw new/delete и использовать std::make_unique и std::make_shared вместо этого.

Чем отличается malloc от new в C++? | PrepBro