Question

I have a coding assignment and I need to free whatever memory I allocate, so I'm trying to delete all the semaphores that my unique_ptr's are pointing to. The unique_ptrs are all in a map. The code snippets:

static map<string, unique_ptr<semaphore>> locks;

This is where all the semaphores are created using "new":

 89         unique_ptr<semaphore>& up = locks[article.title];
 90         if (up == nullptr) {
 91                 up.reset(new semaphore(6));
 92         }

Later, I try to delete the semaphores in the following code:

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         }

And I get the compiler error:

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
Was it helpful?

Solution

All you need to do to delete what a unique_ptr points to is to reset the unique_ptr,

it->second.reset();

OTHER TIPS

The error is clear:

delete takes a pointer as argument, not a unique_ptr. Why you are trying to delete a pointer when you are using unique_ptr for the very same purpose? The point of using smart pointers like unique_prt or shared_ptr is that they automatically delete the pointed object when no longer needed (i.e. out of scope) or you explicitly use reset .

The purpose of std::unique_ptr is to own a memory allocation and automatically delete it when it goes out of scope. IF you actually need to manually release the memory of a unique pointer early, there are ways to do it (reset, etc).

In your specific case, the memory will be automatically freed if you delete the entry in the container.

     for (auto it = locks.begin(), endit = locks.end(); it != endit; ++it) {
             cout << it->first << endl;
             delete it;
     }

Here we are deleting the element of the container, which implicitly calls the unique_ptr's destructor, which deletes the memory it owns.

You can't use this pattern if container's iterators are invalidated by a delete.

If you have full C++11 support you could use:

    for (auto it : locks) {
        std::cout << it.first << '\n';
        delete it.second;
    }

But better still:

    for (auto it : locks)
        std::cout << it.first << '\n';
    locks.clear();

The call to clear will automatically call unique_ptr::~unique_ptr on the value of each element. If you don't have C++11, just replace the for loop with an iterator loop, the call to clear will have the same effect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top