{"id":5309,"date":"2017-09-01T19:33:49","date_gmt":"2017-09-01T19:33:49","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-destructor-rules\/"},"modified":"2023-06-26T12:07:25","modified_gmt":"2023-06-26T12:07:25","slug":"c-core-guidelines-destructor-rules","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-destructor-rules\/","title":{"rendered":"C++ Core Guidelines: Destructor Rules"},"content":{"rendered":"<p>Does my class need a destructor? I often heard this question. Most of the time the answer is no and you are okay with the<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\"> rule of zero<\/a>. Sometimes the answer is yes and we are back to the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\">rule of five<\/a>. To be more precise. The guidelines provide eight rules for destructors.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5308\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/1024px-Max_und_Moritz_Busch_011.png\" alt=\"1024px Max und Moritz Busch 011\" width=\"500\" height=\"233\" style=\"float: right;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/1024px-Max_und_Moritz_Busch_011.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/1024px-Max_und_Moritz_Busch_011-300x139.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/09\/1024px-Max_und_Moritz_Busch_011-768x357.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Here are the eight rules:<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor\">C.30: Define a destructor if a class needs an explicit action at object destruction<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-release\">C.31: All resources acquired by a class must be released by the class\u2019s destructor<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ptr\">C.32: If a class has a raw pointer (<code class=\"highlighter-rouge no-highlight\">T*<\/code>) or reference (<code class=\"highlighter-rouge no-highlight\">T&amp;<\/code>), consider whether it might be owning<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ptr2\">C.33: If a class has an owning pointer member, define <code class=\"highlighter-rouge no-highlight\"><\/code>a destructor<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ref\">C.34: If a class has an owning reference member, define <code class=\"highlighter-rouge no-highlight\"><\/code>a destructor<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-virtual\">C.35: A base class destructor should be either public and virtual, or protected and nonvirtual<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-fail\">C.36: A destructor may not fail<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-noexcept\">C.37: Make destructors <code class=\"highlighter-rouge no-highlight\">noexcept<\/code><\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Let&#8217;s look at each of them in detail.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Destructor_rules\"><\/span>Destructor rules:<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"C30_Define_a_destructor_if_a_class_needs_an_explicit_action_at_object_destruction\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor\">C.30: Define a destructor if a class needs an explicit action at object destruction<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>It&#8217;s characteristic of C++ that a destructor of an object is automatically invoked at the end of its lifetime. More precisely, the object&#8217;s destructor is invoked when the object goes out of scope. Because of this deterministic behavior, you can release highly critical resources in the destructor.<\/p>\n<p>Locks or smart pointers in C++ use this characteristic. Both will automatically release their underlying resource if they go out of scope.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">func<\/span>(){\r\n  std<span style=\"color: #555555;\">::<\/span>unique_ptr<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> uniqPtr <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>make_unique<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">2011<\/span>);\r\n  std<span style=\"color: #555555;\">::<\/span>lock_guard<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>mutex<span style=\"color: #555555;\">&gt;<\/span> lock(mutex);\r\n  . . .\r\n} \/\/ automatically released\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">unipPtr<\/span> releases its int and <span style=\"font-family: courier new,courier;\">lock<\/span> its mutex. Both follow the RAII-idiom (Resource Acquisition Is Initialization). If you are curious about RAII, here is my post <a href=\"https:\/\/www.modernescpp.com\/index.php\/garbage-collectio-no-thanks\">Garbage Collection &#8211; No Thanks, <\/a>including a remark from Bjarne Stroustrup about RAII.<a href=\"https:\/\/www.modernescpp.com\/index.php\/garbage-collectio-no-thanks\"> <\/a><\/p>\n<p>You can also read the rule the other way around. If all your class members have a default destructor, you should not define your own.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Foo<\/span> {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ bad; use the default destructor<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #555555;\">~<\/span>Foo() { s <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">\"\"<\/span>; i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; vi.clear(); }  <span style=\"color: #0099ff; font-style: italic;\">\/\/ clean up<\/span>\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    string s;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> i;\r\n    vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> vi;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C31_All_resources_acquired_by_a_class_must_be_released_by_the_classs_destructor\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-release\">C.31: All resources acquired by a class must be released by the class\u2019s destructor<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>This rule sounds quite apparent and helps you to prevent resource leaks. Right? But you must consider which class members have a complete set of default operations. Now we are once more back to the<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\"> rule of zero or five.<\/a><\/p>\n<p>Maybe the class <span style=\"font-family: courier new,courier;\">File<\/span> has, in contrast to <span style=\"font-family: courier new,courier;\">std::ifstream<\/span>, no destructor, and, therefore, we may get a memory leak if instances of <span style=\"font-family: courier new,courier;\">MyClass<\/span> go out of scope.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">MyClass<\/span>{\r\n    std<span style=\"color: #555555;\">::<\/span>ifstream fstream;   <span style=\"color: #0099ff; font-style: italic;\">\/\/ may own a file<\/span>\r\n    File<span style=\"color: #555555;\">*<\/span> file_;             <span style=\"color: #0099ff; font-style: italic;\">\/\/ may own a file<\/span>\r\n    ... \r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Zbigniew Dubil remarked that the rule should be more specific: All resources <strong>owned<\/strong> by a class must be released by the class&#8217;s destructor. He is right because a class can have a factory creating objects for its clients. There is no need for the class&#8217;s destructor to release the objects.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C32_If_a_class_has_a_raw_pointer_T_or_reference_T_consider_whether_it_might_be_owning\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ptr\">C.32: If a class has a raw pointer (<code class=\"highlighter-rouge no-highlight\">T*<\/code>) or reference (<code class=\"highlighter-rouge no-highlight\">T&amp;<\/code>), consider whether it might be owning<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>There is a question you have to answer if your class has raw pointers or references: who is the owner? If your class is the owner, you have to delete the resource.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C33_If_a_class_has_an_owning_pointer_member_define_a_destructor\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ptr2\">C.33: If a class has an owning pointer member, define <code class=\"highlighter-rouge no-highlight\"><\/code>a destructor<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h3><span class=\"ez-toc-section\" id=\"C34_If_a_class_has_an_owning_reference_member_define_or_a_destructor\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-ref\">C.34: If a class has an owning reference member, define or <code class=\"highlighter-rouge no-highlight\"><\/code>a destructor<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Rules C.33 and C.34 are pretty easy to rephrase. If you own a pointer or a reference, use a smart pointer such as <span style=\"font-family: courier new,courier;\">std::unique_ptr. <\/span><span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> is, by design, as efficient as a raw pointer. So you have no overhead in time or memory but only added value. Here are my posts on the details of <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/smart-pointers\">smart pointers<\/a> in C++.&nbsp;<span style=\"font-family: courier new,courier;\"> <\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"C35_A_base_class_destructor_should_be_either_public_and_virtual_or_protected_and_nonvirtual\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-virtual\">C.35: A base class destructor should be either public and virtual, or protected and nonvirtual<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>This rule sounds very interesting for classes having virtual functions. Let&#8217;s divide it into two parts.<\/p>\n<h4>Public and virtual destructor<\/h4>\n<p>If a class has a public and virtual destructor, you can destroy instances of a derived class through a base class pointer. The same holds for references.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base {  <span style=\"color: #0099ff; font-style: italic;\">\/\/ no virtual destructor<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> f(){};\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived <span style=\"color: #555555;\">:<\/span> Base {\r\n    string s {<span style=\"color: #cc3300;\">\"a resource needing cleanup\"<\/span>};\r\n    <span style=\"color: #555555;\">~<\/span>D() { <span style=\"color: #0099ff; font-style: italic;\">\/* ... do some cleanup ... *\/<\/span> }\r\n};\r\n\r\n...\r\n\r\nBase<span style=\"color: #555555;\">*<\/span> b <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">new<\/span> Derived();\r\n<span style=\"color: #006699; font-weight: bold;\">delete<\/span> b;\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The compiler generates for <span style=\"font-family: courier new,courier;\">Base<\/span> a non-virtual destructor, but deleting an instance of <span style=\"font-family: courier new,courier;\">Derived<\/span> through a <span style=\"font-family: courier new,courier;\">Base<\/span> pointer is undefined behavior if the destructor of <span style=\"font-family: courier new,courier;\">Base<\/span> is non-virtual.<\/p>\n<h4>Protected and nonvirtual destructor<\/h4>\n<p>This is relatively easy to get. If the base class&#8217;s destructor is protected, you can not destroy derived objects using a base class pointer; therefore, the destructor must not be virtual.<\/p>\n<p>Only to make the point clear about types (not pointers or references):<\/p>\n<ul>\n<li>If the destructor of a class <span style=\"font-family: courier new,courier;\">Base<\/span> is private, you can not use the type.<\/li>\n<li>If the destructor of a class <span style=\"font-family: courier new,courier;\">Base<\/span> is protected, you can only derive <span style=\"font-family: courier new,courier;\">Derived<\/span> from <span style=\"font-family: courier new,courier;\">Base<\/span> and use <span style=\"font-family: courier new,courier;\">Derived.<\/span><\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base{\r\n    <span style=\"color: #9999ff;\">protected:<\/span>\r\n    <span style=\"color: #555555;\">~<\/span>Base() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived<span style=\"color: #555555;\">:<\/span> Base{};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    Base b;   \/\/ Error: Base::~Base is protected within this context\r\n    Derived d;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The call <span style=\"font-family: courier new,courier;\">Base b<\/span> will cause an error.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C36_A_destructor_may_not_fail\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-fail\">C.36: A destructor may not fail<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<h3><span class=\"ez-toc-section\" id=\"C37_Make_destructors_noexcept\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-dtor-noexcept\">C.37: Make destructors <code class=\"highlighter-rouge no-highlight\">noexcept<\/code><\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The rule which applies to C.36 and C.37 is quite general. A destructor should not fail, and you should declare it, therefore, as <span style=\"font-family: courier new,courier;\">noexcept.<\/span> I think I should say a few words about <span style=\"font-family: courier new,courier;\">noexcept.<\/span><\/p>\n<ul>\n<li><strong>noexcept: <\/strong>If you declare a function such as a destructor as <span style=\"font-family: courier new,courier;\">noexcept <\/span>an exception thrown in this function will call<a href=\"http:\/\/en.cppreference.com\/w\/cpp\/error\/terminate\"><span style=\"font-family: courier new,courier;\"> std::terminate<\/span><\/a>. <span style=\"font-family: courier new,courier;\">std::terminate<\/span> calls the currently installed <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/error\/terminate_handler\"><span style=\"font-family: courier new,courier;\">std::terminate_handler<\/span><\/a>, which is by default <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/program\/abort\"><span style=\"font-family: courier new,courier;\">std::abort<\/span><\/a>, and your program aborts. By declaring a function&nbsp;<span style=\"font-family: courier new,courier;\">void func() noexcept;<\/span> as <span style=\"font-family: courier new,courier;\">noexcept<\/span> you state:\n<ul>\n<li>My function will not throw an exception.<strong><br \/><\/strong><\/li>\n<li>If my function throws an exception, I will not care and will let the program abort.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>The reason that you should explicitly declare your destructor as <span style=\"font-family: courier new,courier;\">noexcept<\/span> is quite apparent. There is no general way to write error-free code if the destructor could fail. If all of the members of a class have a <span style=\"font-family: courier new,courier;\">noexcept<\/span> destructor, the user-defined or compiler-generated destructor is even implicitly <span style=\"font-family: courier new,courier;\">noexcept.<br \/><\/span><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Whats_next\"><\/span>What&#8217;s next<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Maybe it sounds a bit strange, but after the rules for the destructor, the one for the constructor follows. The C++ core guidelines have about ten rules, and I will write about them in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors\">next post<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Further_Information\"><\/span>Further Information<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>RAII (Resource Acquisition Is Initialization): <a href=\"https:\/\/www.modernescpp.com\/index.php\/garbage-collectio-no-thanks\">Garbage Collection &#8211; No Thanks<\/a><\/li>\n<li>Rule of Zero or Five: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\">Rule of zero of five<\/a><\/li>\n<li>Smart pointers in C++: <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/smart-pointers\">Smart Pointers<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Does my class need a destructor? I often heard this question. Most of the time the answer is no and you are okay with the rule of zero. Sometimes the answer is yes and we are back to the rule of five. To be more precise. The guidelines provide eight rules for destructors.<\/p>\n","protected":false},"author":21,"featured_media":5308,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[499],"class_list":["post-5309","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-classes"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5309"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5309\/revisions"}],"predecessor-version":[{"id":6862,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5309\/revisions\/6862"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5308"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5309"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}