Когда память Dynami c будет уничтожена на карте C ++ с уникальным значением ptr в качестве значения? - PullRequest
0 голосов
/ 08 июля 2020

У меня есть std::map:

std::map<uint64_t, unique_ptr<struct stats>> profile_stats;

И мои функции вставки и удаления выглядят так:

Вставка:

WriteLock(profile_stats_lock);
profile_stats_it it = profile_stats.find(id);
if (it == profile_stats.end()) {
   profile_stats[id] = unique_ptr<stats>(new stats());
}

Удалить:

WriteLock(profile_stats_lock);
profile_stats_it it = profile_stats.find(id);
if (it != profile_stats.end()) {
   profile_stats.erase(it);
}

Будет ли уничтожена динамическая c память для new stats(), выделенная во время вставки, при стирании итератора в функции удаления? Или мне следует сделать что-то, чтобы явно удалить динамическую c память, на которую указывает уникальный указатель?

Ответы [ 2 ]

1 голос
/ 08 июля 2020

Будет ли уничтожена динамическая c память для new stats(), выделенная во время вставки, при стирании итератора в функции удаления?

Да. В этом весь смысл использования unique_ptr. Он освободит для вас память new, когда сама будет уничтожена, например, когда она будет удалена из std::map по любой причине.

Кстати, в вашей функции вставки вы должны использовать std::map::emplace() (или std::map::insert()) вместо std::map::operator[]. operator[] ищет на карте соответствующий ключ, а затем вставляет новый элемент, если ключ не найден. Поскольку вы уже знаете из find(), что id не будет найден, повторное выполнение 2-го сканирования всей карты будет пустой тратой ресурсов.

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args && ... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

...

WriteLock(profile_stats_lock);
profile_stats_it it = profile_stats.find(id);
if (it == profile_stats.end()) {
   profile_stats.emplace(id, make_unique<stats>());
}

В качестве альтернативы, если вы не против тратить впустую потенциально неиспользуемый new, вы можете просто опустить find(), поскольку emplace()insert()) не будет выполнять вставку, если ключ уже существует:

WriteLock(profile_stats_lock);
profile_stats.emplace(id, make_unique<stats>());

Или вы можете пропустить выделение stats, если не вставлен новый элемент карты:

WriteLock(profile_stats_lock);
auto res = profile_stats.emplace(id, nullptr);
if (res.second)
    res.first->second = make_unique<stats>();
1 голос
/ 08 июля 2020

Весь смысл использования таких интеллектуальных указателей заключается в том, что это все автоматические c.

Будет ли динамическая c память для new stats(), выделенная во время insert быть уничтожено при стирании итератора в функции удаления?

Да. Любые такие указатели, оставшиеся на карте, также будут правильно освобождены при уничтожении самой карты.

Также обратите внимание, что std::make_unique<stats>() безопаснее, чем std::unique_ptr<stats>(new stats()), а также требует, чтобы тип был назван только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...