← Назад к вопросам
Приведи пример использования аллокатора памяти
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 аллокаторы дают серьёзное преимущество в скорости и фрагментации памяти.