Jon Deaton
Jon Deaton

Reputation: 4379

How to delete smart pointer to dynamically allocated object?

I made an iterator which when dereferenced returns a copy of std::shared_ptr that points to a dynamically allocated std::pair (created with new in the internals of the iterator). The iterator functions as is, but want to free the pair at the end of the loop to prevent memory leaks.

for (auto it = parser.begin(); it != parser.end(); ++it) {
    shared_ptr<pair<string, string>> record = *it;
    // Analysis of pair
    // delete pair with delete, or reset
}

However, I am having trouble freeing the pair. I have tried delete record, delete *record, and record.reset(), but none of these will compile.

Upvotes: 6

Views: 23483

Answers (2)

Christophe
Christophe

Reputation: 73490

shared_ptr are designed to delete automatically the object they manage, once it is no longer needed. This happens when no shared pointer point anymore to the object (e.g. all the shared pointers pointing to the same object were deleted, or reset to point to another object).

There is no need to delete it yourself. By design, there is even no way to delete the object yourself directly, as this might result in some dangling pointers and inconsistencies.

unique_ptr are another kind of smart pointers. They are designed to keep ownership of an allocated object and destroy the object when the unique pointer itself is destroyed.

Again, there is no need to delete the object yourself. unique_ptr was created to release you from this duty. But here you can destroy the managed object, if you want, by reseting the pointer. As the pointer is unique, there is no risk of creating dangling pointers here.

Finally there are also weak_ptr. These do not own an object, but refer to an object managed by some shared_ptr. The idea is that the existence of a weak_ptr does not prevent the object to be deleted. As the weak_ptr does not own an object, it can't delete it, whatever you do.

Upvotes: 12

Douglas Mencken
Douglas Mencken

Reputation: 101

For my smart pointer, which has overloaded operator delete, I use

struct DeleteIt
{
        template < typename T >
        void operator() ( const T* ptr ) const
        {
                delete ptr ;
        }

        template < typename T >
        void operator() ( const safeptr< T >& ptr ) const
        {
                delete &ptr ;
        }
} ;

And newer GCCs like 7.3 and 8.2 understand delete without &

// this is okay for modern GCC
for ( std::vector< safeptr< Item > >::const_iterator it = items.begin () ; it != items.end () ; ++ it )
{
        delete *it ;
}

// this works with any GCC
for ( std::vector< safeptr< Item > >::const_iterator it = items.begin () ; it != items.end () ; ++ it )
{
        delete &( *it ) ;
}

but GCCs like 4.0.x don’t

Upvotes: 0

Related Questions