{"id":6502,"date":"2023-01-22T18:49:43","date_gmt":"2023-01-22T18:49:43","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/rule-of-zero-or-six\/"},"modified":"2023-08-20T14:37:05","modified_gmt":"2023-08-20T14:37:05","slug":"rule-of-zero-or-six","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/rule-of-zero-or-six\/","title":{"rendered":"The Rule of Zero, or Six"},"content":{"rendered":"<p>The rule of zero, or six, is one of the advanced rules in modern C++. I wrote in my current book &#8220;<a href=\"https:\/\/www.pearson.com\/en-us\/subject-catalog\/p\/c-core-guidelines-explained-best-practices-for-modern-c\/P200000007274\/9780136875673\">C++ Core Guidelines Explained: Best Practices for Modern C++<\/a>&#8221; about them. Today, I want to quote the relevant parts of my book in this post.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" alignleft size-full wp-image-6499\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/classes.png\" alt=\"classes\" width=\"300\" height=\"508\" style=\"float: left;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/classes.png 696w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/classes-177x300.png 177w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/classes-605x1024.png 605w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\">&nbsp;<em>Cippie reasons about the rule of zero, five, or six<\/em>.<\/p>\n<p>&nbsp;<\/p>\n<p>By default, the compiler can generate the big six if needed. You can define the six special member functions, but can also ask explicitly the compiler to provide them with<code> = default<\/code> or delete them with<code> = delete<\/code>.<\/p>\n<h2><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-zero\">C.20: If you can avoid defining any default operations, do<\/a><\/h2>\n<p>This rule is also known as &#8220;<strong>the rule of zero<\/strong>&#8220;. That means, that you can avoid writing any custom constructor, copy\/move constructors, assignment operators, or destructors by using types that support the appropriate copy\/move semantics. This applies to the regular types such as the built-in types <code>bool<\/code> or <code>double<\/code>, but also the containers of the Standard Template Library (STL)such as<code> std::vector<\/code> or <code>std::string<\/code>.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Named_map<\/span> {\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ... no default operations declared ...<\/span>\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>string name;\r\n    std<span style=\"color: #555555;\">::<\/span>map<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> rep;\r\n};\r\n\r\nNamed_map nm;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ default construct<\/span>\r\nNamed_map nm2{nm};  <span style=\"color: #0099ff; font-style: italic;\">\/\/ copy construct<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The default construction and the copy construction work because they are already defined for <code>std::string<\/code> and <code>std::map<\/code>. When the compiler auto-generates the copy constructor for a class, it invokes the copy constructor for all members and all bases of the class.<\/p>\n<h2><a href=\"https:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-five\">C.21: If you define or <code>=delete<\/code> any default operation, define or <code>=delete<\/code> them all<\/a><\/h2>\n<p>The big six are closely related. Due to this relation, you have to define or <code>=delete<\/code> all six. Consequently, this rule is called &#8220;<strong>the rule of six<\/strong>&#8220;. Sometimes, you hear &#8220;<strong>the rule of five<\/strong>&#8220;, because the default constructor is special, and, therefore, sometimes excluded.<\/p>\n<h3 style=\"padding-left: 30px;\">Dependencies between the special member functions<\/h3>\n<p style=\"padding-left: 30px;\">Howard Hinnant developed in his talk at the <a href=\"https:\/\/members.accu.org\/index.php\/conferences\/accu_conference_2014\">ACCU 2014<\/a> conference an overview to the automatically generated special member functions.<\/p>\n<p style=\"padding-left: 30px;\"><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6500\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/DefaultDelete.png\" alt=\"DefaultDelete\" width=\"550\" height=\"354\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/DefaultDelete.png 703w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/DefaultDelete-300x193.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/p>\n<p style=\"padding-left: 30px;\">&nbsp;<\/p>\n<p style=\"padding-left: 30px; text-align: center;\">&nbsp;<em>Automatically generated special member functions<\/em><\/p>\n<p style=\"padding-left: 30px;\">Howard&#8217;s table demands a deep explanation.<\/p>\n<p style=\"padding-left: 30px;\">First of all, user-declared means for one of these six special member functions that you define it explicitly or auto request it from the compiler with <code>=default<\/code>. Deletion of the special member function with <code>=delete<\/code> is also regarded as user declared. Essentially, when you just use the name, such the name of the default constructor, it counts as user declared.<\/p>\n<p style=\"padding-left: 30px;\">When you define any constructor, you get no default constructor. A default constructor is a constructor which can be invoked without an argument.<\/p>\n<p style=\"padding-left: 30px;\">When you define or delete a default constructor with <code>=default<\/code> or <code>=delete<\/code>, no other of the six special member functions is affected.<\/p>\n<p style=\"padding-left: 30px;\">When you define or delete a destructor, a copy constructor, or a copy-assignment operator with<code> =default<\/code> or <code>=delete<\/code>, you get no compiler-generated move-constructor and move-assignment constructor. This means move operations such as move construction or move assignment fall back to copy operations such as copy construction or copy assignment. This fallback automatism is marked in red in the table.<\/p>\n<p style=\"padding-left: 30px;\">&nbsp;&nbsp;&nbsp; When you define or delete with =default<code><\/code> or =delete a move constructor or a move assignment operator, you get only the defined<code> =default<\/code> or <code>=delete<\/code> move constructor or move assignment operator. Consequently, the copy constructor and the copy assignment operator are set to<code> =delete<\/code>. Invoking a copy operation such as copy construction or copy assignment causes, therefore, a compilation error.<\/p>\n<p>When you don&#8217;t follow this rule, you get very unintuitive objects. Here is an unintuitive example from the guidelines.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ doubleFree.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;cstddef&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">BigArray<\/span> {\r\n\r\n <span style=\"color: #9999ff;\">public:<\/span>\r\n    BigArray(std<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">size_t<\/span> len)<span style=\"color: #555555;\">:<\/span> len_(len), data_(<span style=\"color: #006699; font-weight: bold;\">new<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span>[len]) {}\r\n\r\n    <span style=\"color: #555555;\">~<\/span>BigArray(){\r\n        <span style=\"color: #006699; font-weight: bold;\">delete<\/span>[] data_;\r\n    }\r\n\r\n <span style=\"color: #9999ff;\">private:<\/span>\r\n  <span style=\"color: #007788; font-weight: bold;\">size_t<\/span> len_;\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span> data_;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n  \r\n    BigArray bigArray1(<span style=\"color: #ff6600;\">1000<\/span>);\r\n    \r\n    BigArray bigArray2(<span style=\"color: #ff6600;\">1000<\/span>);\r\n    \r\n    bigArray2 <span style=\"color: #555555;\">=<\/span> bigArray1;   <em><span style=\"color: #0099ff;\"> \/\/ (1)<\/span><\/em>\r\n\r\n}                            <em><span style=\"color: #0099ff;\"> \/\/ (2)\r\n<\/span><\/em><\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Why does this program have undefined behavior? The default copy assignment operation <code>bigArray2 = bigArray1<\/code> (1) of the example copies all members of<code> bigArray2<\/code>. Copying means, in particular, that pointer data is copied but not the data. Hence, the destructor for <code>bigArray1<\/code> and <code>bigArray2<\/code> is called (2), and we get undefined behavior because of double free.<\/p>\n<p>The unintuitive behavior of the example is, that the compiler-generated copy assignment operator of <code>BigArray<\/code> makes a shallow copy of BigArray, but the explicitly implemented destructor of <code>BigArray<\/code> assumes ownership of data.<\/p>\n<p><a href=\"https:\/\/www.modernescpp.com\/When%20you%20define%20or%20delete%20a%20destructor,%20a%20copy%20constructor,%20or%20a%20copy-assignment%20operator%20with%20=default%20or%20=delete,%20you%20get%20no%20compiler-generated%20move-constructor%20and%20move-assignment%20constructor.%20This%20means%20move%20operations%20such%20as%20move%20construction%20or%20move%20assignment%20fall%20back%20to%20copy%20operations%20such%20as%20copy%20construction%20or%20copy%20assignment.%20This%20fallback%20automatism%20is%20marked%20in%20red%20in%20the%20table.\">AddressSanitizer<\/a> makes the undefined behavior visible.<\/p>\n<p><em><img loading=\"lazy\" decoding=\"async\" class=\" alignleft size-full wp-image-6501\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/doubleFree.png\" alt=\"doubleFree\" width=\"650\" height=\"387\" style=\"float: left;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/doubleFree.png 977w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/doubleFree-300x178.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/01\/doubleFree-768x457.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/em><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<em>Double free detected with Address Sanitizer<\/em><\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<h2>C.22 Make default operations consistent<\/h2>\n<p>This rule is related to the previous rule. If you implement the default operations with different semantics, the users of the class may become very confused. This strange behavior may also appear if you partially implement the member functions and partially request them via<code> =default<\/code>. You cannot assume that the compiler-generated special member functions have the same semantics as yours.<\/p>\n<p>As an example of the odd behavior, here is the class <code>Strange<\/code>. <code>Strange<\/code> includes a pointer to <code>int<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #00ccff;\"><!-- HTML generated using hilite.me --><\/span><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0099ff;\">\/\/ strange.cpp<\/span><br \/><br \/><span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span><br \/><br \/><span style=\"color: #006699; font-weight: bold;\">struct<\/span> Strange { \r\n  \r\n    Strange()<span style=\"color: #555555;\">:<\/span> p(<span style=\"color: #006699; font-weight: bold;\">new<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span>(<span style=\"color: #ff6600;\">2011<\/span>)) {}\r\n    \r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ deep copy <\/span>\r\n    Strange(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Strange<span style=\"color: #555555;\">&amp;<\/span> a) <span style=\"color: #555555;\">:<\/span> p(<span style=\"color: #006699; font-weight: bold;\">new<\/span> <span style=\"color: #007788; font-weight: bold;\">int<\/span>(<span style=\"color: #555555;\">*<\/span>a.p)) {}                 <em><span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\r\n  \r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ shallow copy<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ equivalent to Strange&amp; operator = (const Strange&amp;) = default;<\/span>\r\n    Strange<span style=\"color: #555555;\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span> <span style=\"color: #555555;\">=<\/span> (<span style=\"color: #006699; font-weight: bold;\">const<\/span> Strange<span style=\"color: #555555;\">&amp;<\/span> a) {       <em><span style=\"color: #0099ff;\">                 \/\/ (2) <\/span> <\/em>         \r\n        p <span style=\"color: #555555;\">=<\/span> a.p;\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #555555;\">*<\/span><span style=\"color: #006699; font-weight: bold;\">this<\/span>;\r\n    }  \r\n   \r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">*<\/span> p;\r\n    \r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Deep copy\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    Strange s1;\r\n    Strange s2(s1);                                              <em><span style=\"color: #0099ff;\"> \/\/ (3)<\/span><\/em>                                   \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"*s2.p = 2017\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    <span style=\"color: #555555;\">*<\/span>s2.p <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2017<\/span>;                                     <em><span style=\"color: #0099ff;\">             \/\/ (4) <\/span> <\/em>                           \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"Shallow copy\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    Strange s3;\r\n    s3 <span style=\"color: #555555;\">=<\/span> s1;                                         <em><span style=\"color: #0099ff;\">              \/\/ (5)    <\/span> <\/em>                               \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span>  <span style=\"color: #cc3300;\">\"*s3.p = 2017\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    <span style=\"color: #555555;\">*<\/span>s3.p <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2017<\/span>;                                    <span style=\"color: #0099ff;\"><em>              \/\/ (6)<\/em>     <\/span>                          \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s1.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s1.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"delete s1.p\"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;                            <em><span style=\"color: #0099ff;\">\/\/ (7) <\/span> <\/em>\r\n    <span style=\"color: #006699; font-weight: bold;\">delete<\/span> s1.p;                                        \r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s2.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s2.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>; <em><span style=\"color: #0099ff;\">\/\/ (8)<\/span><\/em> \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"; *s3.p: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #555555;\">*<\/span>s3.p <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n  \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The class <code>Strange<\/code> has a copy constructor (1) and a copy-assignment operator (2). The copy constructor applies deep copy, and the assignment operator applies shallow copy. By the way, the compiler-generated copy constructor or copy assignment operator also applies shallow copy. Most of the time, you want deep copy semantics (value semantics) for your types, but you probably never want to have different semantics for these two related operations. The difference is that deep copy semantics creates two new separate storage <code>p(new int(*a.p))<\/code> while shallow copy semantics just copies the pointer<code> p = a.p<\/code>. Let\u2019s play with the Strange types. The following figure shows the output of the program.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignleft size-full wp-image-5305\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/08\/strange.png\" alt=\"strange\" width=\"350\" height=\"417\" style=\"float: left;\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<em>Output of <code>strange.cpp<\/code><\/em><\/p>\n<p>Line 3 uses the copy constructor to create <code>s2<\/code>. Displaying the addresses of the pointer and changing the value of the pointer<code> s2.p<\/code> (line 4) shows that <code>s1<\/code> and <code>s2<\/code> are two distinct objects. This is not the case for <code>s1<\/code> and <code>s3<\/code>. The copy-assignment operation in line (5) performs a shallow copy. The result is that changing the pointer<code> s3.p<\/code> (line 6) also affects the pointer<code> s1.p<\/code> because both pointers refer to the same value.<\/p>\n<p>The fun starts if I delete the pointer <code>s1.p<\/code> (line 7). Thanks to the deep copy, nothing bad happens to <code>s2.p<\/code>, but the value of <code>s3.p<\/code> becomes an invalid pointer. To be more precise: Dereferencing an invalid pointer such as in<code> *s3.p<\/code> (line 8) is undefined behavior.<\/p>\n<h2>What&#8217;s Next?<\/h2>\n<p>The idea of a regular type is deeply embodied in the Standard Template Library (STL). The idea goes back to&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Alexander_Stepanov\">Alexander Stephanov<\/a>, who is the creator of the STL. Let me write more about regular types in my next post.<\/p>\n<p>&nbsp;<\/p>\n<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The rule of zero, or six, is one of the advanced rules in modern C++. I wrote in my current book &#8220;C++ Core Guidelines Explained: Best Practices for Modern C++&#8221; about them. Today, I want to quote the relevant parts of my book in this post.<\/p>\n","protected":false},"author":21,"featured_media":6499,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[379],"tags":[494],"class_list":["post-6502","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-patterns","tag-move"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6502","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=6502"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6502\/revisions"}],"predecessor-version":[{"id":8107,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6502\/revisions\/8107"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/6499"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}