{"id":474,"date":"2014-05-25T18:26:57","date_gmt":"2014-05-25T16:26:57","guid":{"rendered":"http:\/\/www.martyndavis.com\/?p=474"},"modified":"2016-07-15T10:14:57","modified_gmt":"2016-07-15T08:14:57","slug":"c-custom-deleters-unique_ptr-vs-shared_ptr","status":"publish","type":"post","link":"https:\/\/www.martyndavis.com\/?p=474","title":{"rendered":"C++ Custom Deleters: unique_ptr vs shared_ptr"},"content":{"rendered":"<p>C++11 gives us two <del>useful<\/del> indispensable smart pointers, <code>std::unique_ptr<\/code> and <code>std::shared_ptr<\/code>. So much has been written about these that there&#8217;s no point me re-hashing anything other than to re-iterate that if you are using &#8220;naked&#8221; <em>owning <\/em> pointers in your code these days, you are simply doing it wrong.<\/p>\n<p>I wanted to mention briefly the use of <strong>custom deleters<\/strong> with smart pointers. If you haven&#8217;t looked at this aspect of smart pointers before, it basically gives us a way to specify <em>what<\/em> should happen when the smart pointer goes out of scope.<br \/>\n<!--more--><br \/>\nBy default, when your smart pointer goes out of scope, <code>delete<\/code> (or <code>delete[]<\/code>, as appropriate) is called on the resource, ensuring that it is cleaned up. Having the ability to specify <em>how<\/em> the resource is deallocated means we can use these smart pointers for other tasks, e.g. emulating C#&#8217;s &#8220;using&#8221; keyword. Another example might be for using a smart pointer for storing a <code>FILE*<\/code> pointer from <code>fopen()<\/code> and calling <code>fclose()<\/code> from the custom deleter.<\/p>\n<p>A further example: I&#8217;ve recently been doing some work with the SDL library. There&#8217;s a library function <code>IMG_Load()<\/code>  which takes an image filename as a parameter. It loads the image, and returns a pointer to an <code>SDL_Surface<\/code> (which represents a bitmap). To free the memory pointed to by the pointer, one needs to call <code>SDL_FreeSurface()<\/code> with the <code>SDL_Surface<\/code> pointer as its parameter. One can neither directly <code>delete<\/code> nor <code>free<\/code> an <code>SDL_Surface<\/code> pointer because it&#8217;s a pointer to a struct, which presumably contains a pointer to some allocated memory within it. So how to use RAII with this construct? Enter custom deleters &#8211; we can specifically tell our smart pointer to call <code>SDL_FreeSurface<\/code> when our smart pointer goes out of scope.<\/p>\n<p>I don&#8217;t specifically want to get into SDL specifics any more than I have, so here&#8217;s a completely self-contained program to replicate what I&#8217;ve been talking about. Note the class &#8220;OldThing&#8221; which pretends to be an old, non-smart resource-allocating API call. <\/p>\n<p>This code also shows the difference between using custom deleters with unique_ptr and shared_ptr which was the original intention of this post. I&#8217;ll explain more about the difference after the listing.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;memory&gt;\r\n\r\nclass OldThing {\r\n  public:\r\n    ~OldThing() \r\n    {\r\n      if (allocated_) {\r\n        std::cout &lt;&lt; &quot;MEMORY LEAK!&quot; &lt;&lt; std::endl;\r\n      }\r\n    }\r\n    void Deallocate()\r\n    {\r\n      std::cout &lt;&lt; &quot;Deallocate called.&quot; &lt;&lt; std::endl;\r\n      allocated_ = false;\r\n    }\r\n  private:\r\n    bool allocated_{ true };\r\n};\r\n\r\nint main() {\r\n  {\r\n    OldThing oldThing;\r\n    \/\/ oldThing going out of scope causes a &quot;memory leak&quot;\r\n  }\r\n\r\n  {\r\n    \/\/ so let's use a smart pointer with a custom &quot;deleter&quot;:\r\n    std::shared_ptr&lt;OldThing&gt; p(new OldThing, \r\n      &#x5B;] (OldThing* ot) {\r\n        ot-&gt;Deallocate();\r\n        delete ot;\r\n      }\r\n    );\r\n  }\r\n\r\n  {\r\n    \/\/ So that works OK. But what if we want\r\n    \/\/ to use unique_ptr instead?\r\n        \r\n    \/\/ 1. Don't try this unless you like \r\n    \/\/ seeing loads of template errors:\r\n    \/*\r\n    std::unique_ptr&lt;OldThing&gt; p(new OldThing, \r\n      &#x5B;] (OldThing* ot) {\r\n        ot-&gt;Deallocate();\r\n        delete ot;\r\n      }\r\n    );\r\n    *\/\r\n\r\n    \/\/ 2. So we need to include the   \r\n    \/\/ deleter's type in the template parameters:\r\n    std::unique_ptr&lt;OldThing, void(*)(OldThing*)&gt; p(new OldThing, \r\n      &#x5B;] (OldThing* ot) {\r\n         ot-&gt;Deallocate();\r\n         delete ot;\r\n      }\r\n    );\r\n  }\r\n\r\n  return 0;\r\n}\r\n<\/pre>\n<p>So to compile this with g++, use <code>g++ -std=c++11 -o foo foo.cpp<\/code> (assuming you&#8217;ve called the source foo.cpp). If you run <code>.\/foo<\/code>, you should see the following output, each line corresponding to one of the three scope blocks in main():<br \/>\n<code><br \/>\nMEMORY LEAK!<br \/>\nDeallocate called.<br \/>\nDeallocate called.<br \/>\n<\/code><\/p>\n<p>Essentially we&#8217;re seeing a fake &#8220;memory leak&#8221; when the non-smart <code>OldThing<\/code> object goes out of scope, then two calls to <code>Deallocate()<\/code> from the two smart pointers. No real memory allocation going on, just calls to the &#8220;deallocation&#8221; method.<\/p>\n<p>Note the difference between specifying a deleter for a <code>shared_ptr<\/code> and a <code>unique_ptr<\/code>. This is the reason for this post&#8230; initially I (without really thinking it through) had some <code>shared_ptr<\/code>s with custom deleters and figured they should really be <code>unique_ptr<\/code>s, so I basically had code like the commented out section marked &#8220;1&#8221;. This generates a spew of template errors and it can be difficult to figure out what&#8217;s going wrong (try it and see).<\/p>\n<p>But to make sense of why we need to specify the deleter differently for a <code>unique_ptr<\/code>, let&#8217;s think about how the two smart pointers are implemented. A <code>shared_ptr<\/code> actually sets up a structure in memory which allows for reference counting, weak pointers, etc. It&#8217;s only when reference counts drop to zero can the resource be deallocated. Its constructor takes a function object as its second parameter to allow us to specify a deleter.<\/p>\n<p>If we don&#8217;t need to share this smart pointer, using a <code>shared_ptr<\/code> is an overhead we don&#8217;t need. A <code>unique_ptr<\/code> is a simpler templated class. If you don&#8217;t specify the deleter&#8217;s function signature as the second template parameter, the <code>default_deleter<\/code> is used. So as you can see in the section marked &#8220;2&#8221; we provide the correct template parameter, a function pointer to a void function that takes an <code>OldThing<\/code> pointer, which makes it work as expected.<\/p>\n<p><strong>Edit:<\/strong> I reviewed this post recently to remind myself about one aspect and realise the way I declare the unique_ptr with a deleter can be simplified to avoid function pointer declarations (which were never very self-explanatory). It just consists of creating the lambda first, then simply using decltype to add the lambda as the template parameter:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nauto dt = &#x5B;]( Foo *f ) {\r\n  delete f;\r\n  std::cout &lt;&lt; &quot;Deleter called\\n&quot;;\r\n  };\r\nstd::unique_ptr&lt;Foo, decltype(dt)&gt; p( new Foo, dt );\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>C++11 gives us two useful indispensable smart pointers, std::unique_ptr and std::shared_ptr. So much has been written about these that there&#8217;s no point me re-hashing anything other than to re-iterate that if you are using &#8220;naked&#8221; owning pointers in your code these days, you are simply doing it wrong. I wanted to mention briefly the use &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.martyndavis.com\/?p=474\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;C++ Custom Deleters: unique_ptr vs shared_ptr&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"_links":{"self":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/474"}],"collection":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=474"}],"version-history":[{"count":27,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/474\/revisions"}],"predecessor-version":[{"id":574,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=\/wp\/v2\/posts\/474\/revisions\/574"}],"wp:attachment":[{"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=474"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=474"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.martyndavis.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=474"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}