
{"id":2559,"date":"2018-12-06T00:06:21","date_gmt":"2018-12-06T05:06:21","guid":{"rendered":"https:\/\/ikriv.com\/blog\/?p=2559"},"modified":"2018-12-06T00:09:33","modified_gmt":"2018-12-06T05:09:33","slug":"forth-to-the-past-c-rvalue-references-t","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=2559","title":{"rendered":"Forth to the past: C++ rvalue references (T&#038;&#038;)"},"content":{"rendered":"<p>This week-end I looked at C++ rvalue references and move semantics.\u00a0<a href=\"https:\/\/github.com\/ikriv\/cpp-move-semantics\">Here&#8217;s the code<\/a>, the good stuff is in\u00a0 <a href=\"https:\/\/github.com\/ikriv\/cpp-move-semantics\/blob\/master\/matrix.h\">matrix.h<\/a>.<\/p>\n<p>Rvalue references seem useful, but <em>way<\/em>\u00a0too treacherous.\u00a0Any programming construct that raises doubts on the nature of objective reality and evokes associations with quantum physics\u00a0(&#8216;reference collapse&#8217; ~ &#8216;wave function collapse&#8217;) is probably too complicated for its own good. But&#8230; maybe you don&#8217;t believe me? The great Scott Meyers explains it beautifully in his <a href=\"&lt;a href=\">channel 9 presentation on rvalue references<\/a>. I was unable to get it right on my own before I watched that.<\/p>\n<p>Rvalue references can be used to reduce unnecessary data copying. I was able to create a matrix class that passes matrices by value, but avoids actually duplicating the data whenever possible. This is great, but let&#8217;s see the laundry list of gotchas I ran into:<\/p>\n<ol>\n<li>Variable of type <code>T&amp;&amp;<\/code> cannot be passed to a function that accepts <code>T&amp;&amp;<\/code>\u00a0(oops!).<\/li>\n<li>You fix it by using <code>forward(v)<\/code> or <code>move(v)<\/code>, but the difference between the two is confusing.<\/li>\n<li>When you see <code>T&amp;&amp;<\/code> in code, it may not in fact be an rvalue reference.<\/li>\n<li>If you are not careful, you may silently get copy behavior instead of move behavior.<\/li>\n<li>Overloads may not work the way you expect.<\/li>\n<\/ol>\n<p>But let&#8217;s start with the good stuff.<\/p>\n<h3>What you can do with rvalue references.<\/h3>\n<p>I created a class\u00a0<code>matrix<\/code>\u00a0with\u00a0<code>operator+<\/code>: complete source at <a href=\"https:\/\/github.com\/ikriv\/cpp-move-semantics\">https:\/\/github.com\/ikriv\/cpp-move-semantics<\/a>.<\/p>\n<p>Rvalue references are traditionally used to optimizing copy constructors and assignment, but they can be as useful in case of operator +. Traditional implementation of such operator for matrices would look something like this:<\/p>\n<pre>matrix operator+(matrix const&amp; a, matrix const&amp; b)\r\n{\r\n    matrix result = a;\r\n    result += b;\r\n    return result;\r\n}<\/pre>\n<p>If we have an experssion like <code>matrix result = a+f(b)+f(c)+d;<\/code>\u00a0the compiler will have no choice, but to create a bunch of temporary matrices and copy a lot of data around. We can significantly reduce the amount of copying by adding rvalue-based overloads of operator +() that modify an rvalue parameter &#8220;in place&#8221; instead of allocating a new matrix. The idea is that rvalue is by definition inaccessible outside the expression, and thus there is no harm in modifying it.<\/p>\n<pre>matrix operator+(matrix&amp;&amp; a, matrix const&amp; b) \/\/ rvalue+lvalue\r\n{\r\n    return std::move(a += b);\r\n}\r\n\r\nmatrix operator+(matrix const&amp; a, matrix&amp;&amp; b) \/\/ lvalue+rvalue\r\n{\r\n    return std::move(b += a);\r\n}\r\n\r\nmatrix operator+(matrix&amp;&amp; left, matrix&amp;&amp; right) \/\/ rvalue+rvalue\r\n{\r\n   return std::move(a += b);\r\n}<\/pre>\n<p>This does improve the performance dramatically. With the move semantics my code allocates 8 matrices. All rvalue reference overloads are conditionally compiled via #define MOVE_SEMANTICS. If I turn that off, the number of matrices allocated jumps to 12 in release mode and to 24 in debug mode.<\/p>\n<p>So, rvalue references <em>are\u00a0<\/em>useful, but they are still a minefield. You must really want those optimizations, and even then if you are not careful, you may not get what you expected. To be continued&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week-end I looked at C++ rvalue references and move semantics.\u00a0Here&#8217;s the code, the good stuff is in\u00a0 matrix.h. Rvalue references seem useful, but way\u00a0too treacherous.\u00a0Any programming construct that raises <a href=\"https:\/\/ikriv.com\/blog\/?p=2559\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[7],"tags":[],"class_list":["entry","author-ikriv","post-2559","post","type-post","status-publish","format-standard","category-cpp"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2559","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2559"}],"version-history":[{"count":48,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2559\/revisions"}],"predecessor-version":[{"id":2611,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2559\/revisions\/2611"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2559"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2559"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2559"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}