1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5<title>Implementing copyable and movable classes</title> 6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> 7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> 9<link rel="up" href="../move.html" title="Chapter 25. Boost.Move"> 10<link rel="prev" href="introduction.html" title="Introduction"> 11<link rel="next" href="composition_inheritance.html" title="Composition or inheritance"> 12</head> 13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 14<table cellpadding="2" width="100%"><tr> 15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> 16<td align="center"><a href="../../../index.html">Home</a></td> 17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> 18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 20<td align="center"><a href="../../../more/index.htm">More</a></td> 21</tr></table> 22<hr> 23<div class="spirit-nav"> 24<a accesskey="p" href="introduction.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../move.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="composition_inheritance.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 25</div> 26<div class="section"> 27<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 28<a name="move.implementing_movable_classes"></a><a class="link" href="implementing_movable_classes.html" title="Implementing copyable and movable classes">Implementing copyable 29 and movable classes</a> 30</h2></div></div></div> 31<div class="toc"><dl class="toc"> 32<dt><span class="section"><a href="implementing_movable_classes.html#move.implementing_movable_classes.copyable_and_movable_cpp0x">Copyable 33 and movable classes in C++0x</a></span></dt> 34<dt><span class="section"><a href="implementing_movable_classes.html#move.implementing_movable_classes.copyable_and_movable_cpp03">Copyable 35 and movable classes in portable syntax for both C++03 and C++0x compilers</a></span></dt> 36</dl></div> 37<div class="section"> 38<div class="titlepage"><div><div><h3 class="title"> 39<a name="move.implementing_movable_classes.copyable_and_movable_cpp0x"></a><a class="link" href="implementing_movable_classes.html#move.implementing_movable_classes.copyable_and_movable_cpp0x" title="Copyable and movable classes in C++0x">Copyable 40 and movable classes in C++0x</a> 41</h3></div></div></div> 42<p> 43 Consider a simple handle class that owns a resource and also provides copy 44 semantics (copy constructor and assignment). For example a <code class="computeroutput"><span class="identifier">clone_ptr</span></code> might own a pointer, and call 45 <code class="computeroutput"><span class="identifier">clone</span><span class="special">()</span></code> 46 on it for copying purposes: 47 </p> 48<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> 49<span class="keyword">class</span> <span class="identifier">clone_ptr</span> 50<span class="special">{</span> 51 <span class="keyword">private</span><span class="special">:</span> 52 <span class="identifier">T</span><span class="special">*</span> <span class="identifier">ptr</span><span class="special">;</span> 53 54 <span class="keyword">public</span><span class="special">:</span> 55 <span class="comment">// construction</span> 56 <span class="keyword">explicit</span> <span class="identifier">clone_ptr</span><span class="special">(</span><span class="identifier">T</span><span class="special">*</span> <span class="identifier">p</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special">{}</span> 57 58 <span class="comment">// destruction</span> 59 <span class="special">~</span><span class="identifier">clone_ptr</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">delete</span> <span class="identifier">ptr</span><span class="special">;</span> <span class="special">}</span> 60 61 <span class="comment">// copy semantics</span> 62 <span class="identifier">clone_ptr</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="identifier">p</span><span class="special">)</span> 63 <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">?</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">-></span><span class="identifier">clone</span><span class="special">()</span> <span class="special">:</span> <span class="number">0</span><span class="special">)</span> <span class="special">{}</span> 64 65 <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="identifier">p</span><span class="special">)</span> 66 <span class="special">{</span> 67 <span class="keyword">if</span> <span class="special">(</span><span class="keyword">this</span> <span class="special">!=</span> <span class="special">&</span><span class="identifier">p</span><span class="special">)</span> 68 <span class="special">{</span> 69 <span class="identifier">T</span> <span class="special">*</span><span class="identifier">p</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">?</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">-></span><span class="identifier">clone</span><span class="special">()</span> <span class="special">:</span> <span class="number">0</span><span class="special">;</span> 70 <span class="keyword">delete</span> <span class="identifier">ptr</span><span class="special">;</span> 71 <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">;</span> 72 <span class="special">}</span> 73 <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span> 74 <span class="special">}</span> 75 76 <span class="comment">// move semantics</span> 77 <span class="identifier">clone_ptr</span><span class="special">(</span><span class="identifier">clone_ptr</span><span class="special">&&</span> <span class="identifier">p</span><span class="special">)</span> 78 <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span> 79 80 <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">clone_ptr</span><span class="special">&&</span> <span class="identifier">p</span><span class="special">)</span> 81 <span class="special">{</span> 82 <span class="keyword">if</span><span class="special">(</span><span class="keyword">this</span> <span class="special">!=</span> <span class="special">&</span><span class="identifier">p</span><span class="special">)</span> 83 <span class="special">{</span> 84 <span class="identifier">std</span><span class="special">::</span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">,</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">);</span> 85 <span class="keyword">delete</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">;</span> 86 <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> 87 <span class="special">}</span> 88 <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span> 89 <span class="special">}</span> 90 91 <span class="comment">// Other operations...</span> 92<span class="special">};</span> 93</pre> 94<p> 95 <code class="computeroutput"><span class="identifier">clone_ptr</span></code> has expected copy 96 constructor and assignment semantics, duplicating resources when copying. 97 Note that copy constructing or assigning a <code class="computeroutput"><span class="identifier">clone_ptr</span></code> 98 is a relatively expensive operation: 99 </p> 100<p> 101</p> 102<pre class="programlisting"><span class="identifier">clone_ptr</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="identifier">p1</span><span class="special">(</span><span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">());</span> 103<span class="comment">// ...</span> 104<span class="identifier">clone_ptr</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="identifier">p2</span> <span class="special">=</span> <span class="identifier">p1</span><span class="special">;</span> <span class="comment">// p2 and p1 each own their own pointer</span> 105</pre> 106<p> 107 </p> 108<p> 109 <code class="computeroutput"><span class="identifier">clone_ptr</span></code> is code that you 110 might find in today's books on C++, except for the part marked as <code class="computeroutput"><span class="identifier">move</span> <span class="identifier">semantics</span></code>. 111 That part is implemented in terms of C++0x <code class="computeroutput"><span class="identifier">rvalue</span> 112 <span class="identifier">references</span></code>. You can find some good 113 introduction and tutorials on rvalue references in these papers: 114 </p> 115<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 116<li class="listitem"> 117 <a href="http://www.artima.com/cppsource/rvalue.html" target="_top"><span class="emphasis"><em>A 118 Brief Introduction to Rvalue References</em></span></a> 119 </li> 120<li class="listitem"> 121 <a href="http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx" target="_top"><span class="emphasis"><em>Rvalue 122 References: C++0x Features in VC10, Part 2</em></span></a> 123 </li> 124</ul></div> 125<p> 126 When the source of the copy is known to be a <code class="computeroutput"><span class="identifier">rvalue</span></code> 127 (e.g.: a temporary object), one can avoid the potentially expensive <code class="computeroutput"><span class="identifier">clone</span><span class="special">()</span></code> 128 operation by pilfering source's pointer (no one will notice!). The move constructor 129 above does exactly that, leaving the rvalue in a default constructed state. 130 The move assignment operator simply does the same freeing old resources. 131 </p> 132<p> 133 Now when code tries to copy a rvalue <code class="computeroutput"><span class="identifier">clone_ptr</span></code>, 134 or if that code explicitly gives permission to consider the source of the 135 copy a rvalue (using <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span></code>), 136 the operation will execute much faster. 137 </p> 138<p> 139</p> 140<pre class="programlisting"><span class="identifier">clone_ptr</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="identifier">p1</span><span class="special">(</span><span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">());</span> 141<span class="comment">// ...</span> 142<span class="identifier">clone_ptr</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="identifier">p2</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">p1</span><span class="special">);</span> <span class="comment">// p2 now owns the pointer instead of p1</span> 143<span class="identifier">p2</span> <span class="special">=</span> <span class="identifier">clone_ptr</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">());</span> <span class="comment">// temporary is moved to p2</span> 144<span class="special">}</span> 145</pre> 146<p> 147 </p> 148</div> 149<div class="section"> 150<div class="titlepage"><div><div><h3 class="title"> 151<a name="move.implementing_movable_classes.copyable_and_movable_cpp03"></a><a class="link" href="implementing_movable_classes.html#move.implementing_movable_classes.copyable_and_movable_cpp03" title="Copyable and movable classes in portable syntax for both C++03 and C++0x compilers">Copyable 152 and movable classes in portable syntax for both C++03 and C++0x compilers</a> 153</h3></div></div></div> 154<p> 155 Many aspects of move semantics can be emulated for compilers not supporting 156 <code class="computeroutput"><span class="identifier">rvalue</span> <span class="identifier">references</span></code> 157 and <span class="bold"><strong>Boost.Move</strong></span> offers tools for that purpose. 158 With <span class="bold"><strong>Boost.Move</strong></span> we can write <code class="computeroutput"><span class="identifier">clone_ptr</span></code> so that it will work both in 159 compilers with rvalue references and those who conform to C++03. You just 160 need to follow these simple steps: 161 </p> 162<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 163<li class="listitem"> 164 Put the following macro in the <span class="bold"><strong>private</strong></span> 165 section: <code class="computeroutput"><a class="link" href="../BOOST_COPYABLE_AND_MOVABLE.html" title="Macro BOOST_COPYABLE_AND_MOVABLE">BOOST_COPYABLE_AND_MOVABLE(classname)</a></code> 166 </li> 167<li class="listitem"> 168 Leave copy constructor as is. 169 </li> 170<li class="listitem"> 171 Write a copy assignment taking the parameter as <code class="computeroutput"><a class="link" href="../BOOST_COPY_ASSIGN_REF.html" title="Macro BOOST_COPY_ASSIGN_REF">BOOST_COPY_ASSIGN_REF(classname)</a></code> 172 </li> 173<li class="listitem"> 174 Write a move constructor and a move assignment taking the parameter as 175 <code class="computeroutput"><a class="link" href="../BOOST_RV_REF.html" title="Macro BOOST_RV_REF">BOOST_RV_REF(classname)</a></code> 176 </li> 177</ul></div> 178<p> 179 Let's see how are applied to <code class="computeroutput"><span class="identifier">clone_ptr</span></code>: 180 </p> 181<p> 182</p> 183<pre class="programlisting"><span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> 184<span class="keyword">class</span> <span class="identifier">clone_ptr</span> 185<span class="special">{</span> 186 <span class="keyword">private</span><span class="special">:</span> 187 <span class="comment">// Mark this class copyable and movable</span> 188 <span class="identifier">BOOST_COPYABLE_AND_MOVABLE</span><span class="special">(</span><span class="identifier">clone_ptr</span><span class="special">)</span> 189 <span class="identifier">T</span><span class="special">*</span> <span class="identifier">ptr</span><span class="special">;</span> 190 191 <span class="keyword">public</span><span class="special">:</span> 192 <span class="comment">// Construction</span> 193 <span class="keyword">explicit</span> <span class="identifier">clone_ptr</span><span class="special">(</span><span class="identifier">T</span><span class="special">*</span> <span class="identifier">p</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special">{}</span> 194 195 <span class="comment">// Destruction</span> 196 <span class="special">~</span><span class="identifier">clone_ptr</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">delete</span> <span class="identifier">ptr</span><span class="special">;</span> <span class="special">}</span> 197 198 <span class="identifier">clone_ptr</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="identifier">p</span><span class="special">)</span> <span class="comment">// Copy constructor (as usual)</span> 199 <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">?</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">-></span><span class="identifier">clone</span><span class="special">()</span> <span class="special">:</span> <span class="number">0</span><span class="special">)</span> <span class="special">{}</span> 200 201 <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">BOOST_COPY_ASSIGN_REF</span><span class="special">(</span><span class="identifier">clone_ptr</span><span class="special">)</span> <span class="identifier">p</span><span class="special">)</span> <span class="comment">// Copy assignment</span> 202 <span class="special">{</span> 203 <span class="keyword">if</span> <span class="special">(</span><span class="keyword">this</span> <span class="special">!=</span> <span class="special">&</span><span class="identifier">p</span><span class="special">){</span> 204 <span class="identifier">T</span> <span class="special">*</span><span class="identifier">tmp_p</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">?</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">-></span><span class="identifier">clone</span><span class="special">()</span> <span class="special">:</span> <span class="number">0</span><span class="special">;</span> 205 <span class="keyword">delete</span> <span class="identifier">ptr</span><span class="special">;</span> 206 <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">tmp_p</span><span class="special">;</span> 207 <span class="special">}</span> 208 <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span> 209 <span class="special">}</span> 210 211 <span class="comment">//Move semantics...</span> 212 <span class="identifier">clone_ptr</span><span class="special">(</span><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">clone_ptr</span><span class="special">)</span> <span class="identifier">p</span><span class="special">)</span> <span class="comment">//Move constructor</span> 213 <span class="special">:</span> <span class="identifier">ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span> 214 215 <span class="identifier">clone_ptr</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="identifier">BOOST_RV_REF</span><span class="special">(</span><span class="identifier">clone_ptr</span><span class="special">)</span> <span class="identifier">p</span><span class="special">)</span> <span class="comment">//Move assignment</span> 216 <span class="special">{</span> 217 <span class="keyword">if</span> <span class="special">(</span><span class="keyword">this</span> <span class="special">!=</span> <span class="special">&</span><span class="identifier">p</span><span class="special">){</span> 218 <span class="keyword">delete</span> <span class="identifier">ptr</span><span class="special">;</span> 219 <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">;</span> 220 <span class="identifier">p</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> 221 <span class="special">}</span> 222 <span class="keyword">return</span> <span class="special">*</span><span class="keyword">this</span><span class="special">;</span> 223 <span class="special">}</span> 224<span class="special">};</span> 225</pre> 226<p> 227 </p> 228</div> 229<p> 230 <span class="bold"><strong>Question</strong></span>: What about types that don't own 231 resources? (E.g. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span></code>?) 232 </p> 233<p> 234 No work needs to be done in that case. The copy constructor is already optimal. 235 </p> 236</div> 237<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 238<td align="left"></td> 239<td align="right"><div class="copyright-footer">Copyright © 2008-2014 Ion Gaztanaga<p> 240 Distributed under the Boost Software License, Version 1.0. (See accompanying 241 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 242 </p> 243</div></td> 244</tr></table> 245<hr> 246<div class="spirit-nav"> 247<a accesskey="p" href="introduction.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../move.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="composition_inheritance.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 248</div> 249</body> 250</html> 251