In this article we will discuss how to use custom deleter with std::shared_ptr.

When a shared_ptr object goes out of scope, its destructor is called. Inside its destructor it decrements the reference count by 1 and if new value of reference count is 0 then it deletes the associated raw pointer.

To delete the internal raw pointer in destructor, by default shared_ptr calls the delete() function i.e.

delete Pointer;

But its not always that we want to use delete function in destruction, there can be other requirements too like,

If shared_ptr object points to an array instead of a simple pointer,

std::shared_ptr<int> p3(new int[12]);

In its destructor shared_ptr will try to delete the int array i.e. int [] by calling
delete

function, whereas as correct way is using
 delete []

Adding custom deleter to shared_ptr<>

In such case we can pass a callback to shared_ptr’s constructor, that will be called from its destructor for deletion i.e.

Custom Deleter as function Pointer

// function that calls the delete [] on received pointer
void deleter(Sample * x)
{
	std::cout << "DELETER FUNCTION CALLED\n";
	delete[] x;
}

Pass the function pointer in constructor of shared_ptr to provide custom deleter i.e.
// Creating a shared+ptr with custom deleter
std::shared_ptr<Sample> p3(new Sample[12], deleter);

Check complete example as follows,
#include <iostream>
#include <memory>

struct Sample
{
	Sample()
	{
		std::cout << "CONSTRUCTOR\n";
	}
	~Sample()
	{
		std::cout << "DESTRUCTOR\n";
	}
};

// function that calls the delete [] on received pointer
void deleter(Sample * x)
{
	std::cout << "DELETER FUNCTION CALLED\n";
	delete[] x;
}

int main()
{
	// Creating a shared+ptr with custom deleter
	std::shared_ptr<Sample> p3(new Sample[12], deleter);
	return 0;
}

Ouput:
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
CONSTRUCTOR
DELETER FUNCTION CALLED
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR
DESTRUCTOR

Custom Deleter as Lambda Function or Function Object

We can also attach Function objects and Lambda functions as callback i.e.,

class Deleter
{
	public:
	void operator() (Sample * x) {
		std::cout<<"DELETER FUNCTION CALLED\n";
		delete[] x;
	}
};

// Function Object as deleter
std::shared_ptr<Sample> p3(new Sample[12], Deleter());

// Lambda function as deleter
std::shared_ptr<Sample> p4(new Sample[12], [](Sample * x){
	std::cout<<"DELETER FUNCTION CALLED\n";
		delete[] x;
});

There might be other cases when we don’t need to delete any memory we just need to releasing memory or resources to a pool etc.

Check out an example with dummy implementation of Memory Pool and Custom Deletor.

#include <iostream>
#include <memory>

struct Sample
{
};

// Memory Pool Dummy Kind of Implementation
template<typename T>
class MemoryPool
{
public:
	T * AquireMemory()
	{
		std::cout << "AQUIRING MEMORY\n";
		return (new T());
	}
	void ReleaseMemory(T * ptr)
	{
		std::cout << "RELEASE MEMORY\n";
		delete ptr;
	}
};
int main()
{
	std::shared_ptr<MemoryPool<Sample> > memoryPoolPtr = std::make_shared<
			MemoryPool<Sample> >();

	std::shared_ptr<Sample> p3(memoryPoolPtr->AquireMemory(),
			std::bind(&MemoryPool<Sample>::ReleaseMemory, memoryPoolPtr,
					std::placeholders::_1));
	return 0;
}

Output:
AQUIRING MEMORY
RELEASE MEMORY

 

Join a list of 2000+ Programmers for latest Tips & Tutorials