TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #844 5.23K
std::allocate_shared
#опытным

В одном из прошлых постов мы упоминали, что одним из недостатков std::make_shared является то, что с ней нельзя использовать кастомный менеджмент памяти.

Причиной является то, что для выделения памяти она использует глобальный new. Поэтому и для освобождения памяти должна использовать глобальный delete. Здесь нет места кастомщине.

Но что, если нам очень нужно по-особенному работать с памятью для объекта? Даже хотя бы просто отслеживать выделение и разрушение без влияния на глобальный delete?

Тут на помощью приходит функция std::allocate_shared. Первым аргументом она принимает аллокатор, который и будет ответственен за выделение и освобождение памяти.

Вот вам простой примерчик с простым STL-совместимым аллокатором, логирующим операции выделения и освобождения памяти:

template <typename T>
class LoggingAllocator {
public:
using value_type = T;
using pointer = T *;
using const_pointer = const T *;
using reference = T &;
using const_reference = const T &;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

template <typename U>
struct rebind {
using other = LoggingAllocator<U>;
};

LoggingAllocator() noexcept = default;

template <typename U>
LoggingAllocator(const LoggingAllocator<U> &) noexcept {}

pointer allocate(size_type n) {
size_type bytes = n * sizeof(T);
std::cout << "Allocating " << n << " elements ("
<< bytes << " bytes)\n";
return static_cast<pointer>(::operator new(bytes));
}

void deallocate(pointer p, size_type n) noexcept {
size_type bytes = n * sizeof(T);
std::cout << "Deallocating " << n << " elements ("
<< bytes << " bytes)\n";
::operator delete(p);
}
};

template <typename T, typename U>
bool operator==(const LoggingAllocator<T> &,
const LoggingAllocator<U> &) noexcept { return true; }

template <typename T, typename U>
bool operator!=(const LoggingAllocator<T> &,
const LoggingAllocator<U> &) noexcept { return false; }

class MyClass {
public:
MyClass(int value) : value(value) {
std::cout << "Constructed with " << value << "\n";
}
~MyClass() {
std::cout << "Destroyed with " << value << "\n";
}
void print() const {
std::cout << "Value: " << value << "\n";
}

private:
int value;
};

int main() {
LoggingAllocator<MyClass> alloc;
auto ptr = std::allocate_shared<MyClass>(alloc, 42);
ptr->print();
return 0;
}
// OUTPUT:
// Allocating 1 elements (24 bytes)
// Constructed with 42
// Value: 42
// Destroyed with 42
// Deallocating 1 elements (24 bytes)


Стандартом на аллокаторы накладываются определенные требования: нужно определить нужные алиасы, методы allocate и deallocate, структуру rebind и соответствующий конструктор копирования и операторы сравнения. Полный список требований можно прочитать тут.

По консольному выводу видно, что аллокатор выделяет немного больше памяти, чем должен занимать объект. Это сделано в том числе для того, чтобы хранить в выделенном куске еще и контрольный блок std::shared_ptr. Так что касаемо особенностей аллокации и деаллокации тут похожая ситуация с std::make_shared.

Аллокатор кстати хранится в том же контрольном блоке, так что информация о способе деаллокации берется оттуда.

Customize your solutions. Stay cool.

#cppcore #STL #memory
  • ❤ 22
  • 👍 14
  • 🔥 9
  • 🤣 1
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →