{"id":263,"date":"2009-06-07T09:45:57","date_gmt":"2009-06-07T08:45:57","guid":{"rendered":"http:\/\/www.nuonsoft.com\/blog\/?p=263"},"modified":"2009-06-07T09:45:57","modified_gmt":"2009-06-07T08:45:57","slug":"the-move-constructor-in-visual-c-2010","status":"publish","type":"post","link":"https:\/\/www.nuonsoft.com\/blog\/2009\/06\/07\/the-move-constructor-in-visual-c-2010\/","title":{"rendered":"The &#8216;Move Constructor&#8217; in Visual C++ 2010"},"content":{"rendered":"<p>A new feature in Visual C++ 2010 is called Rvalue References. This is a feature from the C++0x standard. One thing that Rvalue References can be used for is to implement <strong>move semantics <\/strong>for objects. To add move semantics to a class, we need to implement a <strong>move constructor<\/strong> and a <strong>move assignment operator <\/strong>(optional). This article will briefly explain the benefits of move constructors and how to write them.<!--more--><br \/>\nFor my example I will first define a class called CSomeObject that does not implement any move semantics.<\/p>\n<pre>class CSomeObject\r\n{\r\npublic:\r\n    CSomeObject()\r\n        : m_iBufferSize(0)\r\n        , m_pBuffer(NULL)\r\n        , m_iInstanceID(ms_iInstanceCounter++)\r\n    {\r\n    }\r\n\r\n    \/\/ Normal constructor\r\n    CSomeObject(unsigned int iBufferSize)\r\n        : m_iBufferSize(iBufferSize)\r\n        , m_pBuffer(NULL)\r\n        , m_iInstanceID(ms_iInstanceCounter++)\r\n    {\r\n        if (m_iBufferSize &gt; 0)\r\n        {\r\n            m_pBuffer = new char[m_iBufferSize];\r\n            memset(m_pBuffer, 0, m_iBufferSize);\r\n        }\r\n    }\r\n\r\n    \/\/ Copy constructor\r\n    CSomeObject(const CSomeObject&amp; objSource)\r\n        : m_iInstanceID(ms_iInstanceCounter++)\r\n    {\r\n        m_iBufferSize = objSource.m_iBufferSize;\r\n        if (m_iBufferSize &gt; 0)\r\n        {\r\n            m_pBuffer = new char[m_iBufferSize];\r\n            memset(m_pBuffer, 0, m_iBufferSize);\r\n        }\r\n    }\r\n    ~CSomeObject()\r\n    {\r\n        if (m_pBuffer)\r\n            delete [] m_pBuffer;\r\n        m_pBuffer = NULL;\r\n    }\r\n\r\nprotected:\r\n    unsigned m_iBufferSize;\r\n    char* m_pBuffer;\r\n    int m_iInstanceID;\r\n\u00a0\r\n    static int ms_iInstanceCounter;\r\n};\r\nint CSomeObject::ms_iInstanceCounter = 0;<\/pre>\n<p>Next, I will derive a new class from the above class that will implement a <strong>move constructor<\/strong>.<\/p>\n<pre>class CSomeObjectWithMoveConstructor : public CSomeObject\r\n{\r\npublic:\r\n    CSomeObjectWithMoveConstructor()\r\n        : CSomeObject()\r\n    {\r\n    }\r\n\r\n    \/\/ Normal constructor\r\n    CSomeObjectWithMoveConstructor(unsigned int iBufferSize)\r\n        : CSomeObject(iBufferSize)\r\n    {\r\n    }\r\n\r\n    \/\/ Copy constructor\r\n    CSomeObjectWithMoveConstructor(const CSomeObjectWithMoveConstructor&amp; objSource)\r\n        : CSomeObject(objSource)\r\n    {\r\n    }\r\n\r\n<strong><span style=\"color: #ff0000;\">    \/\/ Move constructor\r\n    CSomeObjectWithMoveConstructor(CSomeObjectWithMoveConstructor&amp;&amp; objSource)\r\n    {\r\n        m_iBufferSize = objSource.m_iBufferSize;\r\n        m_pBuffer = objSource.m_pBuffer;\r\n\r\n        objSource.m_iBufferSize = 0;\r\n        objSource.m_pBuffer = NULL;\r\n    }<\/span>\r\n<\/strong>};<\/pre>\n<p>The move constructor (red code)\u00a0first copies the member variables from the source object to the new object and then sets the variables of the source object to null values. By doing this, the move constructor is actually <strong>moving<\/strong> the memory from m_pBuffer from the source object to the new object. Then it set the m_pBuffer pointer to NULL for the source object to prevent the destructor of the source object to deallocate that memory, because now the new object is the owner of that memory.<\/p>\n<p>Note that you use <strong>&amp;&amp;<\/strong> to declare a Rvalue reference.<\/p>\n<p>The Visual C++ 2010 STL implementation has been updated to use move constructors for objects whenever they are available in a class. For example, the std::vector will automatically use the move constructor when increasing the size of the vector. Previously, the following steps were required for increasing the size of a vector:<\/p>\n<ol>\n<li>A\u00a0new vector with the correct size\u00a0is allocated.<\/li>\n<li>All objects from the old vector\u00a0are <strong>copied <\/strong>to the new vector.<\/li>\n<li>All objects in the old vector are destroyed.<\/li>\n<li>The old vector\u00a0is deallocated.<\/li>\n<\/ol>\n<p>With the move constructor it looks as follows:<\/p>\n<ol>\n<li>A new vector with the correct size is allocated.<\/li>\n<li>All objects from the old vector are <strong>moved<\/strong> to the new vector.<\/li>\n<li>All objects in the old vector are destroyed.<\/li>\n<li>The old vector is deallocated.<\/li>\n<\/ol>\n<p>There doesn&#8217;t seem to be much differences between the two flows. The only thing different is step 2. However, when for example your objects allocate a lot of dynamic memory as in my example class CSomeObject, then the act of copying objects in step 2 can be quite expensive. Using the move constructor, that step becomes much faster as it avoids the dynamic allocation of those buffers. Take the following two loops for example:<\/p>\n<pre>static int siBufferSize = 1024*1024*10;\r\nstatic int siObjectCount = 100;\r\n\/\/ First without move constructor\r\nvector&lt;CSomeObject&gt; vec2;\r\nfor (int i=0; i&lt;siObjectCount; ++i)\r\n{\r\n    vec2.push_back(CSomeObject(siBufferSize));\r\n}\r\n\r\n\/\/ Now with move constructor\r\nvector&lt;CSomeObjectWithMoveConstructor&gt; vec3;\r\nfor (int i=0; i&lt;siObjectCount; ++i)\r\n{\r\n    vec3.push_back(CSomeObjectWithMoveConstructor(siBufferSize));\r\n}<\/pre>\n<p>On my test laptop, the first loop takes around <strong>2600<\/strong> milliseconds, while the second\u00a0loop using move constructors takes only <strong>530<\/strong> milliseconds.<\/p>\n<p>Obviously, move constructors are only useful when you know that the original object will be destroyed, as is the case for the vector example above. It can be used anywhere where temporary objects are involved. For example:<\/p>\n<pre>string str = string(\"hello \") + \"world\";<\/pre>\n<p>Without move constructors, the + operator allocates and returns a new temporary string. With move constructors this object copying is avoided.<\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd293668(VS.100).aspx\" target=\"_blank\">Learn more about Rvalue References in Visual C++ 2010.<\/a><\/p>\n<p>The Visual Studio 2010 project below is a demo application of using move constructors and the performance benefits of using them.<\/p>\n<p><a href=\"http:\/\/www.nuonsoft.com\/downlds\/MoveConstructorDemo.zip\">MoveConstructorDemo.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A new feature in Visual C++ 2010 is called Rvalue References. This is a feature from the C++0x standard. One thing that Rvalue References can be used for is to implement move semantics for objects. To add move semantics to a class, we need to implement a move constructor and a move assignment operator (optional). [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,16,17],"tags":[47,48,45],"class_list":["post-263","post","type-post","status-publish","format-standard","hentry","category-c","category-microsoft","category-software-development","tag-move-constructor","tag-rvalue-references","tag-visual-c-2010"],"_links":{"self":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/263","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/comments?post=263"}],"version-history":[{"count":5,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/263\/revisions"}],"predecessor-version":[{"id":272,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/263\/revisions\/272"}],"wp:attachment":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/media?parent=263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/categories?post=263"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/tags?post=263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}