Удаление того, на что указывает unique_ptr
У меня есть задание на кодирование, и мне нужно освободить всю выделенную память, поэтому я пытаюсь удалить все семафоры, на которые указывает мой unique_ptr. Все unique_ptrs находятся на карте. Фрагменты кода:
static map<string, unique_ptr<semaphore>> locks;
Здесь все семафоры создаются с использованием "new":
89 unique_ptr<semaphore>& up = locks[article.title];
90 if (up == nullptr) {
91 up.reset(new semaphore(6));
92 }
Позже я пытаюсь удалить семафоры в следующем коде:
160 for (map<string, unique_ptr<semaphore>>::iterator it = locks.begin(); it != locks.end();
161 ++it) {
162 cout << it->first << endl;
163 delete it->second;
164 }
И я получаю ошибку компилятора:
news-aggregator.cc: In function âvoid processAllFeeds(const string&)â:
news-aggregator.cc:163:14: error: type âclass std::unique_ptr<semaphore>â argument given to âdeleteâ, expected pointer
make: *** [news-aggregator.o] Error 1
3 ответа
Все, что вам нужно сделать, чтобы удалить то, что unique_ptr
указывает на это reset
unique_ptr
,
it->second.reset();
Ошибка ясна:
delete
занимает pointer
в качестве аргумента, а не unique_ptr
, Почему вы пытаетесь удалить указатель, когда вы используете unique_ptr
для той же цели? Смысл использования умных указателей, таких как unique_prt
или же shared_ptr
заключается в том, что они автоматически удаляют указанный объект, когда он больше не нужен (т.е. выходит за рамки видимости) или вы явно используете reset
,
Цель std::unique_ptr
это владеть распределением памяти и автоматически delete
это когда выходит за рамки. Если вам на самом деле нужно вручную освободить память уникального указателя, есть способы сделать это (reset
, так далее).
В вашем конкретном случае память будет автоматически освобождена, если вы удалите запись в контейнере.
for (auto it = locks.begin(), endit = locks.end(); it != endit; ++it) {
cout << it->first << endl;
delete it;
}
Здесь мы удаляем элемент контейнера, который неявно вызывает unique_ptr
деструктор, который delete
память, которой он владеет.
Вы не можете использовать этот шаблон, если итераторы контейнера становятся недействительными при удалении.
Если у вас есть полная поддержка C++11, вы можете использовать:
for (auto it : locks) {
std::cout << it.first << '\n';
delete it.second;
}
Но еще лучше:
for (auto it : locks)
std::cout << it.first << '\n';
locks.clear();
Призыв к clear
автоматически позвонит unique_ptr::~unique_ptr
на стоимость каждого элемента. Если у вас нет C++11, просто замените цикл for на цикл итератора, вызов clear
будет иметь тот же эффект.