{"id":1182,"date":"2013-08-07T01:00:00","date_gmt":"2013-08-06T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1182"},"modified":"2013-08-09T15:04:04","modified_gmt":"2013-08-09T14:04:04","slug":"pointer-implications-c11","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1182","title":{"rendered":"Pointer Implications (C++11)"},"content":{"rendered":"<p>While C++98 had smart pointers of a sort; they weren\u00e2\u20ac\u2122t good enough for use. The language lacked the key feature that makes smart pointers work: move semantics. C++11 has introduced that language feature, and hence has solid smart pointers.<\/p>\n<p>The addition of smart pointers gives us some further options for passing references to objects when we\u00e2\u20ac\u2122re using C++11. These give us a way of expressing more specifically what a function wants to do with a pointer.<\/p>\n<ul>\n<li><code>f( unique_ptr&lt;O&gt; )<\/code><\/li>\n<li><code>f( shared_ptr&lt;O&gt; )<\/code><\/li>\n<\/ul>\n<p>And some weirdos:<\/p>\n<ul>\n<li><code>f( unique_ptr&lt;O&gt; * )<\/code><\/li>\n<li><code>f( unique_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<li><code>f( const unique_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<li><code>f( shared_ptr&lt;O&gt; * )<\/code><\/li>\n<li><code>f( shared_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<li><code>f( const shared_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<\/ul>\n<h2 id=\"funique_ptro\"><code>f(unique_ptr&lt;O&gt;)<\/code><\/h2>\n<p><code>unique_ptr<\/code> is aptly named: it is a pointer that there can be only one of. There is no way to copy a <code>unique_ptr&lt;&gt;<\/code>, so the following will be disallowed by the compiler:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(unique_ptr&lt;O&gt; p) {\n        <span class=\"co\">\/\/ ... see below ...<\/span>\n    }\n\n    <span class=\"co\">\/\/ ... elsewhere in the forest ...<\/span>\n    unique_ptr&lt;O&gt; myObject = new myObject;\n    <span class=\"co\">\/\/ ERROR: No copying<\/span>\n    unique_ptr&lt;O&gt; copyObject = myObject;\n    <span class=\"co\">\/\/ ERROR: No copying, even for function parameters<\/span>\n    f(myObject);<\/code><\/pre>\n<p>That means that <code>f(unique_ptr&lt;O&gt;)<\/code> is not like <code>f(O*)<\/code>, it\u00e2\u20ac\u2122s saying more than just \u00e2\u20ac\u0153<code>f(p)<\/code> modifies <code>p<\/code>\u00e2\u20ac\u009d. The only way to call this <code>f()<\/code> is by giving up ownership of the passed object, so that there is still only one unique copy of the pointer. Our <code>f()<\/code> declaration therefore tells the caller \u00e2\u20ac\u0153<code>f(p)<\/code> takes ownership of <code>p<\/code> and you need to explicitly give that ownership\u00e2\u20ac\u009d. How do we do that? With move semantics. There is no <code>unique_ptr&lt;&gt;<\/code> copy constructor, but there is a move constructor.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(unique_ptr&lt;O&gt; p) {\n        <span class=\"co\">\/\/ ... see below ...<\/span>\n    }\n\n    <span class=\"co\">\/\/ ... elsewhere in the forest ...<\/span>\n    unique_ptr&lt;O&gt; myObject = new myObject;\n    f(std::move(myObject));\n    <span class=\"co\">\/\/ ERROR: myObject is implicitly now a null unique_ptr&lt;&gt;<\/span>\n    myObject-&gt;modify();<\/code><\/pre>\n<p><code>f()<\/code> here is promising that it will manage the lifetime of the given object (<code>unique_ptr&lt;&gt;<\/code> will, of course, free the underlying resource when it goes out of scope). We can therefore guess the form of <code>f()<\/code> to a certain degree.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(unique_ptr&lt;O&gt; p) {\n        <span class=\"kw\">if<\/span>(p)\n            someGlobalContainer.push_back(std::move(p));\n    }<\/code><\/pre>\n<p>Of particular note: <code>unique_ptr&lt;&gt;<\/code> as a parameter has <em>pointer<\/em> semantics, not reference semantics. That is to say that it can be null, or rather the <code>unique_ptr&lt;&gt;<\/code> representation of null. It includes an <code>operator bool()()<\/code>, which is automatically called in conditional contexts (like <code>if(p)<\/code>), to allow you to check for that null representation. Importantly: you must check for it, just as you would check a pointer parameter was not <code>nullptr<\/code> before you used it.<\/p>\n<p>Other than that, we can see that once <code>f()<\/code> has completed, <code>p<\/code>\u00e2\u20ac\u2122s lifetime is no longer the concern of the caller. We\u00e2\u20ac\u2122ve explicitly said that <code>f()<\/code> takes ownership. <code>f()<\/code> implicitly tells the caller that it must pass an object that has long lifetime \u00e2\u20ac\u201c i.e.\u00c2\u00a0heap storage rather than automatic storage; that\u00e2\u20ac\u2122s pretty much guaranteed by use of a <code>unique_ptr&lt;&gt;<\/code>, which is very hard to trick into taking ownership of automatic storage \u00e2\u20ac\u201c and if you do that then you\u00e2\u20ac\u2122re already seriously broken.<\/p>\n<p>A quick aside to mention the converse case is just as useful in C++11: when a function generates a new object, it should be returned as a <code>unique_ptr&lt;&gt;<\/code> too.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    unique_ptr&lt;O&gt; g() {\n        unique_ptr&lt;O&gt; ret = new O;\n        ret-&gt;configure();\n\n        <span class=\"co\">\/\/ C++11 will automatically use move semantics for a returned<\/span>\n        <span class=\"co\">\/\/ automatic-storage variable<\/span>\n        <span class=\"kw\">return<\/span> ret;\n    }<\/code><\/pre>\n<h2 id=\"fshared_ptro\"><code>f(shared_ptr&lt;O&gt;)<\/code><\/h2>\n<p>It should be getting easy for you now. Unlike in the <code>unique_ptr&lt;&gt;<\/code> case, the caller gets to keep a copy of the pointer. You <em>can<\/em> copy a <code>shared_ptr&lt;&gt;<\/code>. Be aware that a <code>shared_ptr&lt;&gt;<\/code> supplies that facility at non-zero cost. Reference counts have to be maintained, and they have to be atomic, so imply some degree of locking or memory barrier use. Both of which can have performance implications.<\/p>\n<p>That means the following is not illegal:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(shared_ptr&lt;O&gt; p) {\n        <span class=\"co\">\/\/ ... stores a copy ...<\/span>\n    }\n\n    <span class=\"co\">\/\/ ... elsewhere in the forest ...<\/span>\n    shared_ptr&lt;O&gt; myObject = new myObject;\n    f(myObject);\n    <span class=\"co\">\/\/ myObject is still valid<\/span>\n    myObject-&gt;modify();\n    <span class=\"co\">\/\/ When our shared_ptr&lt;O&gt; goes out of scope, the object is not<\/span>\n    <span class=\"co\">\/\/ necessarilly deleted<\/span><\/code><\/pre>\n<p>You have to be a little careful because <code>shared_ptr&lt;&gt;<\/code> means you should only control the object lifetime through <code>shared_ptr&lt;&gt;<\/code>, this combined with the ability to pass unwrapped pointers to a <code>shared_ptr&lt;&gt;<\/code> constructor means you must be careful not to delete the resource yourself.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(shared_ptr&lt;O&gt; p) {\n        <span class=\"co\">\/\/ ... stores a copy ...<\/span>\n    }\n\n    <span class=\"co\">\/\/ ... elsewhere in the forest ...<\/span>\n    O *myObject = new myObject;\n    f(myObject);\n    delete myObject;<\/code><\/pre>\n<h2 id=\"weirdos\">Weirdos<\/h2>\n<ul>\n<li><code>f( unique_ptr&lt;O&gt; * )<\/code><\/li>\n<li><code>f( unique_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<li><code>f( shared_ptr&lt;O&gt; * )<\/code><\/li>\n<li><code>f( shared_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<\/ul>\n<p>Passing a reference to a smart pointer says \u00e2\u20ac\u0153this function will change what your smart pointer refers to\u00e2\u20ac\u009d. The above are not the way to do that. If you have a function that wants to replace a smart pointer, you should be using move semantics and this form:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"co\">\/\/ Used like this: x = f(std::move(x));<\/span>\nunique_ptr&lt;O&gt; f(unique_ptr&lt;O&gt; p) {\n   <span class=\"co\">\/\/ replace<\/span>\n   p = unique_ptr&lt;O&gt;( new O );\n   <span class=\"co\">\/\/ return<\/span>\n   <span class=\"kw\">return<\/span> p;\n}<\/code><\/pre>\n<p>Which more accurately expresses what you\u00e2\u20ac\u2122re doing \u00e2\u20ac\u201c the caller has to explicitly <code>move()<\/code> their <code>unique_ptr&lt;&gt;<\/code> to <code>f()<\/code> as above, and will be given a new pointer back. C++11 will force the use of <code>std::move()<\/code> for the parameter and will automatically use move semantics to get the replacement <code>unique_ptr&lt;&gt;<\/code> back out.<\/p>\n<ul>\n<li><code>f( const unique_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<li><code>f( const shared_ptr&lt;O&gt; &amp; )<\/code><\/li>\n<\/ul>\n<p>Splutter. The function wants to be given control over a smart pointer it\u00e2\u20ac\u2122s not going to modify? Nonsense. There is no reason you\u00e2\u20ac\u2122d do either of these.<\/p>\n<h2 id=\"conclusions\">Conclusions<\/h2>\n<p>Here then is how you should use each of these parameter variations:<\/p>\n<dl>\n<dt><code>f(O&amp;)<\/code><\/dt>\n<dd>\u00e2\u20ac\u0153Modifies an O, which must exist. Does not delete the O. Does not take a copy of O.\u00e2\u20ac\u009d\n<\/dd>\n<dt><code>f(O*)<\/code><\/dt>\n<dd>Don\u00e2\u20ac\u2122t use it. Use <code>f(O&amp;)<\/code>.\n<\/dd>\n<dt><code>f(const O&amp;)<\/code><\/dt>\n<dd>\u00e2\u20ac\u0153Queries an O, which must exist.\u00e2\u20ac\u009d\n<\/dd>\n<dt><code>f(const O*)<\/code><\/dt>\n<dd>\u00e2\u20ac\u0153Queries an O, which might not exist. Provides fallback or exception in the event that the O does not exist\u00e2\u20ac\u009d.\n<\/dd>\n<dt><code>f(unique_ptr&lt;O&gt;)<\/code><\/dt>\n<dd>\u00e2\u20ac\u0153Takes ownership of an O, if it exists. The caller must explicitly give ownership \u00e2\u20ac\u201c meaning it loses it\u00e2\u20ac\u009d.\n<\/dd>\n<dt><code>f(shared_ptr&lt;O&gt;)<\/code><\/dt>\n<dd>\u00e2\u20ac\u0153Takes shared ownership of an O, if it exists. The caller need not explicitly give ownership; however if it is not explicit it must not arbitrarily delete the now-shared O\u00e2\u20ac\u009d.\n<\/dd>\n<\/dl>\n","protected":false},"excerpt":{"rendered":"<p>While C++98 had smart pointers of a sort; they weren\u00e2\u20ac\u2122t good enough for use. The language lacked the key feature that makes smart pointers work: move semantics. C++11 has introduced that language feature, and hence has solid smart pointers. The addition of smart pointers gives us some further options for passing references to objects when\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1182\">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,42,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182"}],"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=1182"}],"version-history":[{"count":3,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182\/revisions"}],"predecessor-version":[{"id":1193,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1182\/revisions\/1193"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}