Custom Deleter in std::unique_ptr

In my previous article, we discussed how std::unique_ptr helps to avoid memory leak. By default it calls the default deleter (C++ delete operator) when the std::unique_ptr goes out of context. But many times default deleter is not good enough for the type of pointer we deal with. For example, if you work with a file pointer (std::FILE *), cleaning up memory does not mean to delete the pointer. You have to close the opened file. Forgetting to close a file is a very common programming mistake in C++. Default deleter does not close a file. Here you have to use your own custom deleter that will perform your custom operation like closing the file.

How to Provide Custom Deleter to std::pointer?

The std::unique_ptr constructor takes two arguments, 1) the pointer that it owns and manages, 2) optionally a deleter which is a function pointer or std::func object. If you don’t specify the second argument, it will use C++ delete operator as default deleter. You can specify your own function as deleter.

// File Name: test.cpp
// To compile: g++ test.cpp -std=c++11
#include <iostream>
#include <fstream>
#include <memory>

void close_file(std::FILE* fp) {
  std::cout << "Closing file..." << std::endl;
  std::fclose(fp);
}

int main() {
  std::ofstream("myfile.txt") << "qnaplus.com";
  std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("myfile.txt", "r"), &close_file);

  char str[16];
  if(fp) {
    std::cout << std::fgets(str, 16, fp.get()) << std::endl;
  }
  return 0;
}

Here, in time of creating the std::unique_ptr we provided a file pointer, fp, and our custom deleter function close_file(). When the std::unique_ptr will go out of context, the close_file() function will get called that will close the file. As we specified a custom deleter, default delete would not get called.

Lamda Function as Deleter

We can use a lamda function as deleter also. The same solution can be written as follows. This program and the above are basically same.

#include <iostream>
#include <fstream>
#include <memory>

int main() {
  std::ofstream("myfile.txt") << "qnaplus.com";
  std::unique_ptr<std::FILE, std::function<void(std::FILE *)>> fp(std::fopen("myfile.txt", "r"),
                                                           [](std::FILE *f){
                                                               std::cout << "Closing file..." << std::endl;
                                                               std::fclose(f);
                                                           });

  char str[16];
  if(fp) {
    std::cout << std::fgets(str, 16, fp.get()) << std::endl;
  }
  return 0;
}

Author: Srikanta

I write here to help the readers learn and understand computer programing, algorithms, networking, OS concepts etc. in a simple way. I have 20 years of working experience in computer networking and industrial automation.


If you also want to contribute, click here.

Leave a Reply

Your email address will not be published. Required fields are marked *

0
1
1
0
0
0