{"id":1180,"date":"2013-08-06T01:00:00","date_gmt":"2013-08-05T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1180"},"modified":"2013-08-09T15:04:02","modified_gmt":"2013-08-09T14:04:02","slug":"pointer-implications-c","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1180","title":{"rendered":"Pointer Implications (C++)"},"content":{"rendered":"<p>Last time we covered pointer arguments, and that article was applicable to C and C++. C++ introduced true pass-by-reference semantics.<\/p>\n<ul>\n<li><code>f( O &amp; )<\/code><\/li>\n<li><code>f( const O &amp; )<\/code><\/li>\n<\/ul>\n<h2 id=\"fo\"><code>f(O &amp;)<\/code><\/h2>\n<p>Previously we were careful to note that passing a pointer to a function was still only pass-by-value. The pointer was copied, and then the function was free to use that pointer to modify the underlying object. That was how C provided the utility of pass-by-reference without actually having to implement it. C++ lets us declare a real reference type. We can then use the variable in the function as we would if it were inline in the caller.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"dt\">void<\/span> f(O &amp;p) {\n        p.modify();\n    }<\/code><\/pre>\n<p>Barring the different syntax (\u00e2\u20ac\u0153<code>.<\/code>\u00e2\u20ac\u009d instead of \u00e2\u20ac\u0153<code>-&gt;<\/code>\u00e2\u20ac\u009d), there is one fundamental difference between pass-by-reference and pass-by-pointer: null is not a valid value. You can only pass a reference to an object that exists. It\u00e2\u20ac\u2122s not possible to call <code>f(nullptr)<\/code> since <code>nullptr<\/code> is a pointer not an object. It\u00e2\u20ac\u2122s not possible to call <code>f(*nullptr)<\/code>, since dereferencing <code>nullptr<\/code> is illegal. Therefore <code>f()<\/code> doesn\u00e2\u20ac\u2122t need to check for <code>nullptr<\/code> itself.<\/p>\n<p>We\u00e2\u20ac\u2122re also cutting off any ability for <code>f()<\/code> to affect the lifetime of <code>p<\/code>. Whereas in the <code>f(O*)<\/code> case, <code>f()<\/code> could modify the object <em>and<\/em> delete it; in the <code>f(O&amp;)<\/code> case, <code>f()<\/code> cannot <code>delete<\/code> the object, since <code>delete<\/code> requires a pointer (I\u00e2\u20ac\u2122m ignoring the insane case of <code>delete &amp;p<\/code>).<\/p>\n<p>That fact makes <code>f(O&amp;)<\/code> far more attractive as a \u00e2\u20ac\u0153modifies O\u00e2\u20ac\u009d function declaration that <code>f(O*)<\/code>. In fact, if you find yourself writing <code>f(O*)<\/code>, think very carefully about whether you really have got the correct form.<\/p>\n<h2 id=\"fconst-o\"><code>f(const O &amp;)<\/code><\/h2>\n<p>This is an easy one; excepting the change of syntax, this is identical to <code>f(const O *)<\/code> saving the fact that it\u00e2\u20ac\u2122s not possible to pass <code>nullptr<\/code> to it.<\/p>\n<p>Like <code>f(O*)<\/code> and <code>f(O&amp;)<\/code>, there is reason to pick between <code>f(const O*)<\/code> and <code>f(const O&amp;)<\/code>:<\/p>\n<dl>\n<dt><code>f(const O&amp;)<\/code><\/dt>\n<dd>\n<p><code>f()<\/code> queries an <code>O<\/code><\/p>\n<\/dd>\n<dt><code>f(const O*)<\/code><\/dt>\n<dd>\n<p><code>f()<\/code> queries an <code>O<\/code> with a fallback if this <code>O<\/code> doesn\u00e2\u20ac\u2122t exist.<\/p>\n<\/dd>\n<\/dl>\n<p>Choose between them as appropriate for your application. On the whole though, you should prefer <code>f(const O&amp;)<\/code>, since you should only work with objects that exist \u00e2\u20ac\u201c why would you even call <code>f()<\/code> if you had nothing to call it with?<\/p>\n<hr \/>\n<p>Next time, C++11.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time we covered pointer arguments, and that article was applicable to C and C++. C++ introduced true pass-by-reference semantics. f( O &amp; ) f( const O &amp; ) f(O &amp;) Previously we were careful to note that passing a pointer to a function was still only pass-by-value. The pointer was copied, and then the\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1180\">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,42,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1180"}],"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=1180"}],"version-history":[{"count":3,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1180\/revisions"}],"predecessor-version":[{"id":1191,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1180\/revisions\/1191"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}