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

Как работать с транзакцией в SQL?

1.3 Junior🔥 181 комментариев
#Базы данных и SQL

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

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

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

Ответ: new - оператор динамического выделения памяти

Оператор new в C++ выделяет память в heap (динамическую память) и возвращает указатель на неё. Это основной способ работы с объектами переменного размера.

Как работает new

Шаг 1: Выделение памяти

int* ptr = new int;           // Выделяет 4 байта в heap
int* array = new int[100];    // Выделяет 400 байт в heap
MyClass* obj = new MyClass(); // Выделяет sizeof(MyClass) байт

Оператор new:

  1. Вызывает operator new(size) - выделяет место в heap
  2. Вызывает конструктор (если это класс)
  3. Возвращает указатель на выделенную память

Шаг 2: Использование

int* ptr = new int(42);  // Выделил и инициализировал

std::cout << *ptr << std::endl;  // Разыменовываем, 42
std::cout << ptr[0] << std::endl;  // Массив

delete ptr;  // Освобождаем память
ptr = nullptr;  // ❌ Не автоматически!

Сравнение со стеком

// На стеке (автоматическая память)
{
    int x = 5;              // stack: создаётся
    MyClass obj;            // stack: вызывается конструктор
}  // Выходим из scope: деструктор, память освобождена

// На heap (динамическая память)
{
    int* ptr = new int(5);           // heap: выделяется
    MyClass* obj = new MyClass();    // heap: вызывается конструктор
}  // Выходим из scope: УТЕЧКА ПАМЯТИ!
   // delete забыли вызвать

Под капотом

Память heap

Виртуальное адресное пространство процесса:
┌─────────────────────┐
│  Text (код)         │ 0x00000000
├─────────────────────┤
│  Data (инициализ.)  │
├─────────────────────┤
│  BSS (неинициализ.) │
├─────────────────────┤
│  Heap    ↓          │  new выделяет отсюда
│  [метаданные][данные][свободно]
├─────────────────────┤
│  ...                │  промежуток
├─────────────────────┤
│  Stack   ↑          │
│  [локальные переменные]
│  [return addresses] │
│  [параметры функций]│
└─────────────────────┘ 0xFFFFFFFF

Этот промежуток заполняется в обе стороны: heap растёт вверх, stack вниз.

Внутренние метаданные

// Когда вызываем new int[100], БД создаёт:
struct AllocationBlock {
    size_t size;         // 400 байт (для 100 ints)
    void* prev;          // Указатель на предыдущий блок
    void* next;          // Указатель на следующий блок
    // ...
};

// Память в heap:
┌──────────────────┐
│  [метаданные]    │  ← указатель, который вернёт new
│  [100 ints]      │
│  [метаданные]    │  следующего блока
│  [другие данные] │
└──────────────────┘

При delete нужно знать размер, он хранится в метаданных.

Типы new

1. new для одного объекта

MyClass* obj = new MyClass();
// Вызывает конструктор
delete obj;  // Вызывает деструктор

2. new для массива

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

❌ ВАЖНО: delete vs delete[]

int* single = new int(5);
int* array = new int[5];

delete single;    // OK
delete[] array;   // OK

// Если перепутаешь:
delete array;     // ❌ Undefined behavior! Может быть утечка
delete[] single;  // ❌ Undefined behavior!

3. Размещающий new (Placement new)

char buffer[sizeof(MyClass)];
MyClass* obj = new(buffer) MyClass();  // Выделяет в buffer!

// Деструктор вызываем вручную
obj->~MyClass();
// delete НЕ вызываем!

Используется когда нужна память в конкретном месте.

Оператор new можно переопределить

class MyClass {
public:
    void* operator new(size_t size) {
        std::cout << "Allocating " << size << " bytes" << std::endl;
        return malloc(size);
    }
    
    void operator delete(void* ptr) {
        std::cout << "Freeing memory" << std::endl;
        free(ptr);
    }
};

MyClass* obj = new MyClass();  // Вызовет operator new
delete obj;                     // Вызовет operator delete

Современный подход: smart pointers

❌ Старый способ

MyClass* obj = new MyClass();  // ручное управление
// ... множество кода ...
if (error) {
    return;  // Забыли delete!
}
delete obj;  // может не выполниться

✅ Новый способ (C++11+)

std::unique_ptr<MyClass> obj = std::make_unique<MyClass>();
// obj.get() - получить сырой указатель
// obj.reset() - удалить и выделить новое
}  // Автоматически delete

std::shared_ptr<MyClass> shared = std::make_shared<MyClass>();
}  // Автоматически delete (reference counting)

Исключения при new

try {
    int* huge = new int[1000000000000];  // Много памяти
} catch (const std::bad_alloc& e) {
    std::cerr << "Memory allocation failed: " << e.what() << std::endl;
}

// Или nothrow версия
int* ptr = new(std::nothrow) int[1000000000000];
if (ptr == nullptr) {
    std::cerr << "Allocation failed" << std::endl;
}

Производительность

// ❌ Медленно: много маленьких выделений
for (int i = 0; i < 1000000; ++i) {
    int* x = new int(i);  // 1 миллион new операций
    // Работаем
    delete x;             // 1 миллион delete операций
}

// ✅ Быстро: одно большое выделение
std::vector<int> data;
data.reserve(1000000);  // Одно выделение
for (int i = 0; i < 1000000; ++i) {
    data.push_back(i);
}
// Автоматическое удаление при выходе из scope

Утечки памяти

// ❌ Утечка
MyClass* obj = new MyClass();
do_something(obj);
// delete забыли!

// ❌ Утечка в исключении
void function() {
    MyClass* obj = new MyClass();
    dangerous_operation();  // Может выкинуть исключение
    delete obj;  // Может не выполниться
}

// ✅ RAII
void function() {
    std::unique_ptr<MyClass> obj = std::make_unique<MyClass>();
    dangerous_operation();  // Выкинет исключение? obj уничтожится автоматически
}

Инструменты для debug

# Valgrind - найти утечки
valgrind --leak-check=full ./program

# AddressSanitizer (ASan)
g++ -fsanitize=address program.cpp
./a.out  # Покажет утечки

# Clang memory profiler
clang++ -fprofile-instr-generate program.cpp

Итог

new выделяет память в heap ✅ Возвращает указатель на выделенную память ✅ delete освобождает память ✅ delete[] для массивов (не забудь!) ✅ Smart pointers (unique_ptr, shared_ptr) - автоматическое управление ⚠️ Забыл delete = утечка памяти ⚠️ double delete = undefined behavior ⚠️ delete [] vs delete - важно различать! ⚠️ Старайся избегать сырых new/delete - используй RAII