{"id":1072,"date":"2013-06-22T01:00:00","date_gmt":"2013-06-21T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1072"},"modified":"2013-06-26T11:34:18","modified_gmt":"2013-06-26T10:34:18","slug":"copy-and-swap-idiom","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1072","title":{"rendered":"Copy and Swap Idiom"},"content":{"rendered":"<p>I learned a new trick today, while reading about C++11 (of which more to come). It\u00e2\u20ac\u2122s a technique I wish I\u00e2\u20ac\u2122d known about a long time ago, as it addresses an issue I\u00e2\u20ac\u2122ve always thought C++ had \u00e2\u20ac\u201c forcing you to duplicate code. That issue is addressed even more thoroughly with C++11, which has introduced the ability for one constructor to call another (about time on that one).<\/p>\n<p>The trick I learned is called the <em>copy and swap idiom<\/em>; and I thought I\u00e2\u20ac\u2122d go through it bit by bit in case it\u00e2\u20ac\u2122s news to anyone else.<\/p>\n<p>So\u00e2\u20ac\u00a6 you\u00e2\u20ac\u2122re writing a C++ object to manage a resource. This is a fairly typical thing to do in C++, whether it be a file descriptor, a lock, a thread, a GUI object handle, or a chunk of memory. The resource has its own lifetime and is allocated, used and deallocated.<\/p>\n<p>To begin then we would always deal with allocation and deallocation. That means constructor(s) and destructor:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    class T {\n      public:\n        T( size_t s ) :\n            mResource( s ? new <span class=\"dt\">uint8_t<\/span>[s] : nullptr )\n            mSize(s) {}\n        ~T() {\n            delete[] mResource;\n        }\n\n      private:\n        <span class=\"dt\">uint8_t<\/span> *mResource;\n        <span class=\"dt\">int<\/span> mSize;\n    };<\/code><\/pre>\n<p>Once we start using this resource though, we want to be able to copy it.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    T obj1(<span class=\"dv\">100<\/span>);\n    T obj2(obj1);<\/code><\/pre>\n<p>Let\u00e2\u20ac\u2122s write a reasonable one:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    class T {\n        <span class=\"co\">\/\/ ...<\/span>\n        <span class=\"co\">\/\/ Use C++11 facility for calling constructors<\/span>\n        T( <span class=\"dt\">const<\/span> T &amp;O ) :\n            T(O.s)\n        {\n            <span class=\"co\">\/\/ Use STL algorithm, copy(), to do the hard work<\/span>\n            copy(O.mResource, O.mResource + O.mSize, mResource);\n        }\n        <span class=\"co\">\/\/ ...<\/span>\n    };<\/code><\/pre>\n<p>Once we have a copy constructor we\u00e2\u20ac\u2122ll also want an assignment operator. Before I learned the magic trick under discussion, here\u00e2\u20ac\u2122s the sort of code I might have written:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    class T {\n        <span class=\"co\">\/\/ ...<\/span>\n        T&amp; operator=T( <span class=\"dt\">const<\/span> T &amp;O )\n        {\n            <span class=\"kw\">if<\/span>( &amp;O == this )\n                <span class=\"kw\">return<\/span> *this;\n            delete[] mResource;\n            mResource = new <span class=\"dt\">uint8_t<\/span>[O.mSize];\n            mSize = O.mSize;\n            <span class=\"kw\">return<\/span> *this;\n        }\n        <span class=\"co\">\/\/ ...<\/span>\n    };<\/code><\/pre>\n<p>Hopefully you can see how unsatisfactory that is. We\u00e2\u20ac\u2122ve had to duplicate the destructor and constructor code inside the assignment operator. As the object becomes more complicated we\u00e2\u20ac\u2122ll have to maintain that connection \u00e2\u20ac\u201c every change to constructor or destructor has to be repeated. Yuck. I had thought that was just a C++ annoyance. Not so. Here\u00e2\u20ac\u2122s the copy-and-swap idiom:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    class T {\n        <span class=\"co\">\/\/ ...<\/span>\n        T&amp; operator=T( T O )\n        {\n            swap(O);\n            <span class=\"kw\">return<\/span> *this;\n        }\n\n        <span class=\"dt\">void<\/span> swap( T &amp;O )\n        {\n            <span class=\"co\">\/\/ STL swap from the utility\/algorithm include<\/span>\n            using std::swap;\n            swap(mResource, O.mResource);\n            swap(mSize, O.mSize);\n        }\n        <span class=\"co\">\/\/ ...<\/span>\n    };<\/code><\/pre>\n<p>The most important change is that the parameter to <code>operator=()<\/code> is no longer a <code>const<\/code> reference, it\u00e2\u20ac\u2122s a value. This would normally be have your C++ spidey-sense worrying about unnecessary copies. Remember though, in this case we are performing a <em>necessary and requested copy<\/em>.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    T a(<span class=\"dv\">100<\/span>);\n    T b(<span class=\"dv\">0<\/span>);\n\n    b = a;<\/code><\/pre>\n<p>What happens in the <code>b = a<\/code> line now? The compiler sees that there is an <code>operator=()<\/code> available, but it uses pass-by-value. It therefore effectively does this:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    T a(<span class=\"dv\">100<\/span>);\n    T b(<span class=\"dv\">0<\/span>);\n\n    b.operator=(T(a));<\/code><\/pre>\n<p>In other words, it calls the copy constructor with <code>a<\/code> to make a new temporary <code>T<\/code>. This does a deep-copy before <code>operator=()<\/code> even begins. Then <code>operator=()<\/code> does one thing: <code>swap()<\/code> to switch the resources owned by the temporary and the destination. That leaves us with a temporary, about to be deleted, pointing at <code>b<\/code>\u00e2\u20ac\u2122s old resources and <code>b<\/code> pointing at the copy-constructed from <code>a<\/code> resources. Then <code>operator=()<\/code> ends and the temporary goes out of scope, causing its destructor to free up <code>b<\/code>\u00e2\u20ac\u2122s original resources.<\/p>\n<p>I think that\u00e2\u20ac\u2122s magical \u00e2\u20ac\u201c remember that the code duplication was of the destructor code to free up the original resources (now handled when the temporary goes out of scope using the destructor itself); and of the copy-constructor code to perform the deep-copy (now done automatically by the creation of the temporary using the copy-constructor itself). There is no need to check for self-assignment, since the temporary cannot be an alias for anything \u00e2\u20ac\u201c it\u00e2\u20ac\u2122s newly created. What\u00e2\u20ac\u2122s more there is not a pointer in sight.<\/p>\n<p>Things get even better when we introduce C++11\u00e2\u20ac\u2122s new move-semantics. Move semantics in C++11 are used to bypass unnecessary copy operations when the thing being copied from is a temporary. Consider this:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    T b(T(<span class=\"dv\">50<\/span>));<\/code><\/pre>\n<p><code>b<\/code> is being assigned to as a copy of a temporary object. Before C++11, the compiler would call the constructor to make a temporary, then call <code>b<\/code>\u00e2\u20ac\u2122s copy constructor to deep-copy that temporary to <code>b<\/code>, then destruct the temporary. That\u00e2\u20ac\u2122s pretty wasteful; we had to pay for a copy we didn\u00e2\u20ac\u2122t want, and an allocation and destruction we didn\u00e2\u20ac\u2122t want. Plus we needed twice the memory we eventually used. (This isn\u00e2\u20ac\u2122t actually what happens, the compiler is allowed to use something called <em>copy elision<\/em> in this case to avoid the copy, but there are other more complex cases where <em>copy elision<\/em> isn\u00e2\u20ac\u2122t possible).<\/p>\n<p>C++11 lets us catch this case separately from normal copy construction. When the thing being copied from a temporary (C++11 calls them <em>rvalues<\/em>), a different constructor will be looked for in preference to the copy-constructor \u00e2\u20ac\u201c the move-constructor:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    class T {\n        <span class=\"co\">\/\/ ...<\/span>\n        T( T &amp;&amp;O ) :\n            T(<span class=\"dv\">0<\/span>)\n        {\n            swap(O);\n        }\n        <span class=\"co\">\/\/ ...<\/span>\n    };<\/code><\/pre>\n<p>The identifying feature is the double-ampersand and lack of <code>const<\/code> on the argument, which means an <em>rvalue reference<\/em>, and will match a temporary. The particular feature of the move constructor is that we are allowed to do whatever we like to the source object because we know it\u00e2\u20ac\u2122s not going to exist once the current C++ statement is complete (i.e.\u00c2\u00a0until the next semi-colon).<\/p>\n<p>We first construct the smallest possible valid object <code>T(0)<\/code>, and then use the same copy-and-swap trick we did earlier to swap the resources of the <em>rvalue<\/em> into the newly constructed object. That leaves the temporary resource pointing at the \u00e2\u20ac\u0153not-used\u00e2\u20ac\u009d state. When it destructs, it takes no resources with it, but we are left with the resources it did have.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    T b(T(<span class=\"dv\">50<\/span>));<\/code><\/pre>\n<p>Now this line goes much faster. A temporary, <code>T(50)<\/code> is constructed, <code>b<\/code>\u00e2\u20ac\u2122s <em>move<\/em> constructor is called with that temporary, which constructs a <code>T(0)<\/code> and then swaps it for the temporary <code>T(50)<\/code>. That leaves <code>b<\/code> set up as a <code>T(50)<\/code> and the temporary as a <code>T(0)<\/code>, which is then destructed at negligible cost. <code>b<\/code> is exactly what we want, and it cost us one full construction and one negligible construction; no deep-copy was needed and no extra memory was used.<\/p>\n<p>Key elements that make move-construction practical:<\/p>\n<ul>\n<li>Members that are <code>swap()<\/code>able. For fast swaps, the members should themselves be move-constructable and move-assignable.<\/li>\n<li>Valid-but-empty state. That is to say that you can quickly construct an resource-free version of the object (our <code>T(0)<\/code> above allocated nothing, leaving the resource pointer set to <code>nullptr<\/code>).<\/li>\n<li>A fast destructor. In its empty-but-valid state, the destructor shouldn\u00e2\u20ac\u2122t have to do anything. That\u00e2\u20ac\u2122s the case with our sample <code>T<\/code>, because the <code>nullptr<\/code> resource costs nothing to <code>delete<\/code>.<\/li>\n<\/ul>\n<p>Not having the above doesn\u00e2\u20ac\u2122t make move-construction impossible, but it would deny you some of the speed advantages.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I learned a new trick today, while reading about C++11 (of which more to come). It\u00e2\u20ac\u2122s a technique I wish I\u00e2\u20ac\u2122d known about a long time ago, as it addresses an issue I\u00e2\u20ac\u2122ve always thought C++ had \u00e2\u20ac\u201c forcing you to duplicate code. That issue is addressed even more thoroughly with C++11, which has introduced\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1072\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[66,82,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1072"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1072"}],"version-history":[{"count":6,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1072\/revisions"}],"predecessor-version":[{"id":1084,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1072\/revisions\/1084"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1072"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1072"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1072"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}