Tuesday, May 3, 2011

Videos from ACCU Talks Now Available

The fine folks behind the 2011 ACCU Conference recorded my technical presentations, and those videos are now online as follows:
Viewing these videos is the next best thing to having been to the sessions, provided your definition of the next best thing includes having a seat at the extreme left end of Row 1. The video is nothing to tweet home about (especially if you want to read the text on the slides), but the audio is quite nice. One thing you're likely to find attractive is that the way the video is exposed, I'm hidden much of the time.

Enjoy!

Scott

12 comments:

petke said...

Much appreciated!

Josh Peterson said...

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.

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!

Scott Meyers said...

The presentation materials are now available via this blog post as well as my Past Talks page.

Scott

Josh Peterson said...

Thanks Scott, I appreciate it!

filodej said...

Hello Scott,
thank you very much for providing the videos and slides. It was very enlightening for me (especially the false sharing).
I have a question regarding the move assignment implementation.
In your presentation you have said that the Widget class implementation you presented is a conventional and widely accepted/expected one.
Stephan T. Lavavej's in his rvalue reference lecture presented a different version - the assignment with the rhs argument passed by value:

class Widget: public WidgetBase {
public:
 Widget(Widget const& rhs) { … }
 Widget(Widget&& rhs) { … }
 Widget& operator=(Widget rhs)
 {
  rhs.swap(*this);
  return *this;
 }
 …
};

I like this one very much because it is basically 2in1 implementation (it reminds me of the copy&swap idiom in the copy assignment).
What do you think about this version?
Thanks very much again.
Best Regards,
Petr

Scott Meyers said...

@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.

Scott

filodej said...

Yes, you are right.
The std::array<> seems to be a typical example where neither swap nor move can be implemented efficiently.
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.
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 rhs argument).

For example:

// move constructor + swap
Widget w = create_widget();
// copy constructor + swap
Widget w2 = w;

Or did I miss something?

Kind regards,
Petr

Scott Meyers said...

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 C++11 training materials:

A generic, “clever” (i.e., suspicious) way to implement move assignment for a type T is

T& operator=(T&& rhs) {
swap(rhs, *this);
return *this;
}

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 http://thbecker.net/articles/rvalue_references/section_04.html and http://cpp-next.com/archive/2009/09/your-next-assignment/.

filodej said...

Hi Scott,
thank you for the links (especially the latter one gave me exactly the information I was looking for).

Just to summarize my understanding about implementing the move assignment operator:
- Using swap with argument passed as rvalue reference is not a good idea (due to possibly postponed user-visible side-effects of the left-hand-side)
- Using swap with argument passed as value is OK, but may be slightly less efficient when assigning from an lvalue (due to copying "too eagerly")

Thanks very much for your time.
Petr

Scott Meyers said...

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.

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.)

Scott

filodej said...

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:

class Widget: public WidgetBase {
public:
Widget(Widget const& rhs): data(rhs.data) {}
Widget(Widget&& rhs): data(std::move(rhs.data) {}
Widget& operator=(Widget rhs)
{
rhs.swap(*this);
return *this;
}

private:
std::vector data;
};

then in effect I have implemented the move assignment (because it takes advantage of the move constructor for rhs value creation whenever possible) - e.g. in the following statement:

Widget w = create_widget();

the following sequence occurs:
1) A new Widget is created and returned as rvalue
2) A new temporary is created via move constructor
3) w.operator= swaps *this and the rhs temporary
The article Your new assignment you linked in your previous answer considers this approach as a "canonical" form of implementing copy+move assignments both at once.
Best regards,
Petr

Scott Meyers said...

The cost of a move assignment in your approach consists of the following:

1. Move-construct rhs.
2. Move rhs's value into *this, which in your implementation is accomplished via a swap.
3. Destruct rhs.

In a "real" move assignment operator, there would be no need for steps 1 and 3.

Scott