Добавить в корзинуПозвонить
Найти в Дзене

Как создать std::unique_ptr

Как создать std::unique_ptr? В этом посте я постараюсь рассмотреть все способы создания std::unique_ptr. Если я что-то забыл — традиционно жду вас в комментариях🙂 📌Способ 1. С помощью вызова конструктора Этот способ появился в C++11: выделяем память под объект и передаём указатель в конструктор std::unique_ptr. const std::unique_ptr<int> v1(new int(1)); 📌Способ 2. Используем std::make_unique Этот способ появился в C++14 для предотвращения утечки памяти. Баг с утечкой памяти пофиксили в C++17, но до сих пор использование std::make_unique — один из самых распространённых способов создания std::unique_ptr. Под капотом он полностью идентичен Способу 1. const auto v2 = std::make_unique<int>(2); 📌Способ 3. Используем std::make_unique_for_overwrite Этот способ появился в C++20. std::make_unique_for_overwrite выделяет память под ресурс, но ресурс при этом default-initialized В примере ниже массив int не инициализируется const auto v3 = std::make_unique_for_overwrite<int[]>(2); 📌Спосо

Как создать std::unique_ptr?

В этом посте я постараюсь рассмотреть все способы создания std::unique_ptr. Если я что-то забыл — традиционно жду вас в комментариях🙂

📌Способ 1. С помощью вызова конструктора

Этот способ появился в C++11: выделяем память под объект и передаём указатель в конструктор std::unique_ptr.

const std::unique_ptr<int> v1(new int(1));

📌Способ 2. Используем std::make_unique

Этот способ появился в C++14 для предотвращения утечки памяти. Баг с утечкой памяти пофиксили в C++17, но до сих пор использование std::make_unique — один из самых распространённых способов создания std::unique_ptr. Под капотом он полностью идентичен Способу 1.

const auto v2 = std::make_unique<int>(2);

📌Способ 3. Используем std::make_unique_for_overwrite

Этот способ появился в C++20. std::make_unique_for_overwrite выделяет память под ресурс, но ресурс при этом default-initialized В примере ниже массив int не инициализируется

const auto v3 = std::make_unique_for_overwrite<int[]>(2);

📌Способ 4. Используем пользовательский удалитель

Хотя способ появился ещё в C++11, он до сих пор остаётся одной из незаслуженно обделённых вниманием возможностей C++. Вспомните про него, когда вам придёт в голову мысль написать RAII-обёртку для C-шных указателей на ресурс😉

void customDeleter(int* value)

{

std::cout << "Custom deleter for value: " << *value << '\n';

delete value;

}

using custom_deleter_t = std::unique_ptr<int, decltype(&customDeleter)>;

custom_deleter_t v4(new int(4), &customDeleter);

📌Способ 5. Перемещаем ресурс из другого std::unique_ptr

Напоминаю: перемещать можно только неконстантный std::unique_ptr.

custom_deleter_t v5(new int(5), &customDeleter);

v5 = std::move(v4);

📌Способ 6. Заменяем ресурс во владении

На самом деле это просто Способ 5 под капотом😎

custom_deleter_t v6(new int(6), &customDeleter);

v6.reset(v5.release());

📌Способ 7. Вы ещё не устали?😁

Благодаря RVO std::unique_ptr можно возвращать как результат выполнения функции.

std::unique_ptr<int> makeInt(int value)

{

std::unique_ptr<int> result;

// Тяжёлые подготовительные операции для создания объекта :)

value /= 2;

result = std::make_unique<int>(value);

return result;

}

const auto v7 = makeInt(14);

Полный код с примерами из поста я выложил в комментариях. Удачных экспериментов🚀