Удаление того, на что указывает 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 будет иметь тот же эффект.

Другие вопросы по тегам