tag:blogger.com,1999:blog-7101933101966798446.post4594763273405835240..comments2024-03-28T10:33:06.910-07:00Comments on The View from Aristeia: Videos from ACCU Talks Now AvailableScott Meyershttp://www.blogger.com/profile/05280964633768289328noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-7101933101966798446.post-35518436305901861632012-03-16T13:26:49.047-07:002012-03-16T13:26:49.047-07:00The cost of a move assignment in your approach con...The cost of a move assignment in your approach consists of the following:<br /><br />1. Move-construct rhs.<br />2. Move rhs's value into *this, which in your implementation is accomplished via a swap.<br />3. Destruct rhs.<br /><br />In a "real" move assignment operator, there would be no need for steps 1 and 3. <br /><br />ScottScott Meyershttps://www.blogger.com/profile/05280964633768289328noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-52205150632458872842012-03-16T12:36:15.673-07:002012-03-16T12:36:15.673-07:00Sorry for reiterating the issue again, but still I...Sorry for reiterating the issue again, but still I am little bit confused. It seems to me that if I implement move constructor and then the assignment operator accepting parameter by value, like this:<br /><i><br />class Widget: public WidgetBase {<br />public:<br /> Widget(Widget const& rhs): data(rhs.data) {}<br /> Widget(Widget&& rhs): data(std::move(rhs.data) {}<br /> Widget& operator=(Widget rhs)<br /> {<br /> rhs.swap(*this);<br /> return *this;<br /> }<br /> …<br />private: <br /> std::vector data;<br />};<br /></i><br />then in effect I <i>have</i> implemented the move assignment (because it takes advantage of the move constructor for rhs value creation whenever possible) - e.g. in the following statement:<br /><i><br />Widget w = create_widget();<br /></i><br />the following sequence occurs:<br />1) A new Widget is created and returned as rvalue<br />2) A new temporary is created via move constructor<br />3) w.operator= swaps *this and the rhs temporary<br />The article <a href="http://cpp-next.com/archive/2009/09/your-next-assignment/" rel="nofollow">Your new assignment</a> you linked in your previous answer considers this approach as a "canonical" form of implementing copy+move assignments both at once. <br />Best regards,<br />Petrfilodejhttps://www.blogger.com/profile/17389359539567562061noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-84591148085784111992012-03-16T09:44:38.327-07:002012-03-16T09:44:38.327-07:00If you're implementing a move operation (i.e.,...If you're implementing a move operation (i.e., move constructor or move assignment operator), you will, by definition, always want to take your parameter by rvalue reference. If you take your parameter by value, it's not a move operation.<br /><br />Regarding the choice between passing by value or passing by lvalue-reference-to-const, my advice is to pass by value only if you will unconditionally make a copy of the parameter. In that case, passing by value permits compilers to perform some optimizations they might otherwise not perform. But if the copy is not unconditional, you can end up paying for a copy where none is required. (Note that his advice is not specific to the copy assignment operator. It applies to all functions. The only thing special about the copy assignment operator is that it often performs an unconditional copy of its parameter.)<br /><br />ScottScott Meyershttps://www.blogger.com/profile/05280964633768289328noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-44016273307069212242012-03-16T02:07:43.650-07:002012-03-16T02:07:43.650-07:00Hi Scott,
thank you for the links (especially the ...Hi Scott,<br />thank you for the links (especially the latter one gave me exactly the information I was looking for).<br /><br />Just to summarize my understanding about implementing the move assignment operator:<br />- Using swap with argument passed <i>as rvalue reference</i> is not a good idea (due to possibly postponed user-visible side-effects of the left-hand-side)<br />- Using swap with argument passed <i>as value</i> is OK, but may be slightly less efficient when assigning from an lvalue (due to copying "too eagerly")<br /><br />Thanks very much for your time.<br />Petrfilodejhttps://www.blogger.com/profile/17389359539567562061noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-2589520061522697002012-03-15T12:47:36.746-07:002012-03-15T12:47:36.746-07:00As a general rule, you don't want to implement...As a general rule, you don't want to implement the move operations using swap, i.e., move-and-swap is generally an anti-pattern. This is what I say about it in my <a href="http://www.artima.com/shop/overview_of_the_new_cpp" rel="nofollow">C++11 training materials</a>:<br /><br />A generic, “clever” (i.e., suspicious) way to implement move assignment for a type T is<br /><br />T& operator=(T&& rhs) { <br /> swap(rhs, *this); <br /> return *this; <br />}<br /><br />This has the effect of swapping the contents of *this and rhs. The idea is that because rhs is an rvalue reference, it’s bound to an rvalue, and that rvalue will be destroyed at the end of the statement containing the assignment. When it is, the data formerly associated with *this will be destroyed (e.g., resources will be released). The problem is that rhs may actually correspond to an lvalue that has been explicitly std::move’d, and in that case, the lvalue may not be destroyed until later than expected. That can be problematic. Details can be found at <a href="http://thbecker.net/articles/rvalue_references/section_04.html" rel="nofollow">http://thbecker.net/articles/rvalue_references/section_04.html</a> and <a href="http://cpp-next.com/archive/2009/09/your-next-assignment/" rel="nofollow">http://cpp-next.com/archive/2009/09/your-next-assignment/</a>.Scott Meyershttps://www.blogger.com/profile/05280964633768289328noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-1409447174241957322012-03-15T11:03:27.835-07:002012-03-15T11:03:27.835-07:00Yes, you are right.
The std::array<> seems t...Yes, you are right.<br />The std::array<> seems to be a typical example where neither swap nor move can be implemented efficiently.<br />If we focus only on classes where the move semantics can buy us something then the single-assignment pattern seems better to me than the one with two assignments.<br />Although it seems to apply the copy&swap, the presence of the move constructor makes it actually much better - makes it (copy|move)&swap (compiler can decide whether it is possible to call move constructor instead of copy constructor for the <i>rhs</i> argument).<br /><br />For example:<br /><i><br />// move constructor + swap<br />Widget w = create_widget();<br />// copy constructor + swap<br />Widget w2 = w;<br /></i><br />Or did I miss something?<br /><br />Kind regards,<br />Petrfilodejhttps://www.blogger.com/profile/17389359539567562061noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-36928141050778212952012-03-15T10:23:15.260-07:002012-03-15T10:23:15.260-07:00@filodej: The code you posted *is* the copy-and-sw...@filodej: The code you posted *is* the copy-and-swap idiom in the copy assignment operator. If copy-and-swap is how you want to implement copy assignment, what you show is a fine way to implement it. But for some types, copy-and-swap is more expensive than need be. An example of this would be the copy assignment operator for std::array. For a std::array object of size n, implementing the copy operator= via copy-and-swap means copying 3n values, but implementing it via the conventional approach (i.e., declaring operator='s parameter to be a reference) calls for copying only n values.<br /><br />ScottScott Meyershttps://www.blogger.com/profile/05280964633768289328noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-85594361118426400682012-03-15T07:18:50.899-07:002012-03-15T07:18:50.899-07:00Hello Scott,
thank you very much for providing the...Hello Scott,<br />thank you very much for providing the videos and slides. It was very enlightening for me (especially the false sharing).<br />I have a question regarding the move assignment implementation. <br />In your presentation you have said that the <i>Widget class</i> implementation you presented is a conventional and widely accepted/expected one.<br />Stephan T. Lavavej's in his <a href="http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n" rel="nofollow">rvalue reference lecture</a> presented a different version - the assignment with the <i>rhs</i> argument passed by value:<br /><i><br />class Widget: public WidgetBase {<br />public:<br /> Widget(Widget const& rhs) { … }<br /> Widget(Widget&& rhs) { … }<br /> Widget& operator=(Widget rhs)<br /> {<br /> rhs.swap(*this);<br /> return *this;<br /> }<br /> …<br />};<br /></i><br />I like this one very much because it is basically 2in1 implementation (it reminds me of the copy&swap idiom in the copy assignment).<br />What do you think about this version?<br />Thanks very much again.<br />Best Regards,<br />Petrfilodejhttps://www.blogger.com/profile/17389359539567562061noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-26756641349580737592011-05-09T04:05:03.302-07:002011-05-09T04:05:03.302-07:00Thanks Scott, I appreciate it!Thanks Scott, I appreciate it!Josh Petersonhttps://www.blogger.com/profile/06610939891275333243noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-36583273030818704792011-05-08T22:49:42.815-07:002011-05-08T22:49:42.815-07:00The presentation materials are now available via t...The presentation materials are now available via <a href="http://scottmeyers.blogspot.com/2011/05/presentation-materials-from-accu-talks.html" rel="nofollow">this blog post</a> as well as my <a href="http://www.aristeia.com/presentations.html" rel="nofollow">Past Talks page</a>.<br /><br />ScottScott Meyershttps://www.blogger.com/profile/05280964633768289328noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-394448526424362452011-05-06T12:27:58.587-07:002011-05-06T12:27:58.587-07:00Yes, thanks Scott, I very much enjoyed the talk. ...Yes, thanks Scott, I very much enjoyed the talk. You mentioned that you might make the slides available (at least to those who were in attendance). I was not in attendance at the conference, unfortunately.<br /><br />Are you willing to make the slide with the links you mentioned at the end available? I would like to follow up by reading that content. If you can, I would greatly appreciate it. Thanks!Josh Petersonhttps://www.blogger.com/profile/06610939891275333243noreply@blogger.comtag:blogger.com,1999:blog-7101933101966798446.post-19073926076293353422011-05-04T06:40:50.282-07:002011-05-04T06:40:50.282-07:00Much appreciated!Much appreciated!petkenoreply@blogger.com