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

Приведи пример использования аллокатора памяти

1.7 Middle🔥 181 комментариев
#Структуры данных и алгоритмы#Язык C++

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

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

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

Приведи пример использования аллокатора памяти

Аллокаторы памяти — это мощный инструмент для оптимизации работы с памятью в C++. Вот практические примеры:

1. Стандартный аллокатор (std::allocator)

Стандартный аллокатор работает с операциями new/delete:

#include <vector>
#include <memory>

// Используется по умолчанию
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);

2. Стек-аллокатор (Stack Allocator)

Оптимален для временных объектов в функции:

#include <memory>
#include <vector>

template <typename T, size_t N>
class StackAllocator {
private:
    std::array<T, N> buffer;
    size_t used = 0;

public:
    T* allocate(size_t n) {
        if (used + n > N) throw std::bad_alloc();
        T* ptr = &buffer[used];
        used += n;
        return ptr;
    }

    void deallocate(T* p, size_t n) {
        // Stack allocator обычно не использует деаллокацию
    }
};

// Использование
StackAllocator<int, 1000> stack_alloc;
std::vector<int, StackAllocator<int, 1000>> vec(stack_alloc);
for (int i = 0; i < 100; ++i) {
    vec.push_back(i);
}

3. Pool аллокатор

Для часто создаваемых одинаковых объектов:

template <typename T>
class PoolAllocator {
private:
    struct Node {
        T data;
        Node* next;
    };

    Node* free_list = nullptr;
    std::vector<Node*> pools;

public:
    T* allocate() {
        if (free_list) {
            Node* node = free_list;
            free_list = free_list->next;
            return &node->data;
        }
        // Выделить новый блок
        Node* new_pool = new Node[100];
        pools.push_back(new_pool);
        return &new_pool[0].data;
    }

    void deallocate(T* ptr) {
        // Вернуть объект в free list
        Node* node = reinterpret_cast<Node*>(ptr);
        node->next = free_list;
        free_list = node;
    }

    ~PoolAllocator() {
        for (auto pool : pools) delete[] pool;
    }
};

// Использование
PoolAllocator<std::string> string_pool;
for (int i = 0; i < 1000; ++i) {
    std::string* str = string_pool.allocate();
    new (str) std::string("hello");
    // ...
    str->~string();
    string_pool.deallocate(str);
}

4. Arena аллокатор

Для группы объектов с одинаковым временем жизни:

class ArenaAllocator {
private:
    std::vector<char> arena;
    size_t offset = 0;

public:
    void* allocate(size_t size) {
        if (offset + size > arena.capacity()) {
            arena.reserve(arena.capacity() * 2 + size);
        }
        void* ptr = arena.data() + offset;
        offset += size;
        return ptr;
    }

    void reset() { offset = 0; }
};

5. Пример с std::vector и custom allocator

template <typename T>
class TrackingAllocator : public std::allocator<T> {
private:
    static size_t total_allocated;
    static size_t total_deallocated;

public:
    T* allocate(size_t n) {
        total_allocated += n * sizeof(T);
        std::cout << "Выделено: " << n * sizeof(T) << " байт\n";
        return std::allocator<T>::allocate(n);
    }

    void deallocate(T* p, size_t n) {
        total_deallocated += n * sizeof(T);
        std::cout << "Освобождено: " << n * sizeof(T) << " байт\n";
        std::allocator<T>::deallocate(p, n);
    }
};

template <typename T> size_t TrackingAllocator<T>::total_allocated = 0;
template <typename T> size_t TrackingAllocator<T>::total_deallocated = 0;

int main() {
    std::vector<int, TrackingAllocator<int>> vec;
    vec.resize(100);
    std::cout << "Всего выделено: " 
              << TrackingAllocator<int>::total_allocated << "\n";
    return 0;
}

Когда использовать

  • Stack Allocator — временные буферы в функциях, фиксированный размер
  • Pool Allocator — много малых объектов одного типа
  • Arena Allocator — группы объектов с одинаковым lifetime
  • Tracking Allocator — профилирование и отладка утечек памяти

Практическое применение

В production backend системах:

  • Game engines используют arena allocators для уровней
  • Web серверы используют pool allocators для коннекшенов
  • Финтех системы используют stack allocators для обработки квотировок
  • Базы данных используют custom allocators для оптимизации cache

Стандартный std::allocator покрывает 90% случаев, но для high-performance систем custom аллокаторы дают серьёзное преимущество в скорости и фрагментации памяти.