Tag Archives: repost

ACCU 2011 Nuggets: 2. Move semantics

Or: “This is C++: everything is a lie”

This nugget from Scott Meyers’s talk on Perfect Forwarding, slides here.

I should point out that I’m pretty late to the scene here; the original proposal is more than four years old, and far sharper people closer to the source have already written concisely and exhaustively on this topic.

Essentially, the problem that needed solving is the following:

  vector<string> split(string const & to_be_split, string const & splitter) { 
    vector<string> result;
    // how can we return a vector here without lots of copying
    // or an annoying out parameter polluting our method signature?
    // or by having to bind the result to a const &?
    return result;
  }

N.B The original version of this post involved changing the return type of split to be an rvalue reference. That is somewhat out of date, and also very dangerous! In fact, if you’re using an up to date compiler and you implemented split with that signature, the code would use the perfect forwarding provided by vector such that no copying occurs.

  // Here, splitByComma would be move constructed from the result of
  // split. Even in older C++ versions, you still might get lucky and find
  // the copy is elided by return value optimization
  vector<string> const splitByComma(split(string("foo,bar,baz"), string(",")));

Further (and better) motivations and examples of move semantics are detailed here (I highly recommend reading some of this before progressing).

So, we want to write code that will take advantage of this new move support in C++11. In order to do this, we need an understanding of what is safely movable from! It turns out that C++ already has concepts within it to allow us to reason about this without completely losing our sanity: lvalues, rvalues, and lvalue references.

Scott provides the following handy guide for identifying whether a particular variable is an lvalue, an lvalue reference or an rvalue.

lvalues: things you can take the address of

  • string const foo("asdf") // foo is an lvalue
  • int i, *pInt // all of i, pInt and *pInt are lvalues

lvalue references: what you think of as references now (both of our arguments to split from earlier)

rvalues: things you cannot take the address of (unnamed temporaries)

  • split("foo, bar, baz", ","); //both characters strings are rvalues
  • function returns (result from split)

In general:

  • You can’t move from an lvalue (other people can still use it – what happens when they do?). Never do this. OK, almost never (see alternative title).
  • You can move from an rvalue (no-one can get at it – you’re safe!). One might say you should move from an rvalue, unless the cost of copying is irrelevant.

These rules are handy, but there’s one more major gotcha to go. Let’s assume that someone has already made std::string compatible with move semantics ( so it has a move constructor: std::string(std::string &&) ).

  class StringMoverPuzzle {
  public:
    StringMoverPuzzle(string && to_be_moved) :
      moved_string_(to_be_moved) // do we copy or move here?
    {}
  private:
    string const moved_string_;
  };

The answer is annoying – in fact, the copy constructor is called! Outrage! We labelled our parameter with &&, it should be an rvalue, damnit! Look further though, it has a name (to_be_moved), and, if we were in the body of the constructor, we could take its address. Shock, horror, it’s an lvalue!

So when we try to construct our moved_string_, the compiler looks for a constructor that takes an lvalue rather than the rvalue we were hoping for, and we end up copying (curses!).

The solution?

    FixedStringMover(string && to_be_moved) :
      moved_string_(std::move(to_be_moved))
    {}

That handy call to std::move is actually just a cast – we’re casting away the lvalueness of to_be_moved so that the correct string constructor is used.

This isn’t anything like the end of the move story (and I haven’t got anywhere near ‘perfect’ forwarding), but I thought the mind break of rvalue reference becoming lvalue was worth a post of its own.

For further material, I highly recommend Scott’s slides, or the video of the session here.

ACCU 2011 Nuggets: 1. Hide and seek

ACCU 2011 Nuggets : short distillations of ideas presented at the 2011 ACCU conference.
My first nugget is from Giles Colborne‘s talk on simplicity (slides here).
Giles categorised the types of usability improvements you could make into four species: Reduce, Reorganise, Hide, and Displace.
I want discuss the hiding case then share Giles’s illustrative example of how to best execute this.

Hide!

We need to make two good choices in order for hiding to work.
  1. What features should we hide?
  2. Having hidden them, how does our user access these features?
Well (you say), you could hide the less used features, then have some sort of ‘reveal’ button to allow access again. You could even adaptively work out which features to hide over the first week or so of real usage. In extreme cases, you could even talk to your users to find out what they might want. It turns out that it’s very hard to get this approach right. Colborne cited various examples where this was very badly done: the menus in Microsoft Office (or your Start Menu) being a prime suspect. Think of the video remote control with the button you always need hidden behind the protective “expert” cover (hat tip Ewan Milne for that example).

Is there a better way?

Colborne regaled us of a time when he was browsing the New York Times website, and came across a word he didn’t know: “Bodega”. Naturally, he highlighted the word, ready for the standard copy-paste into Google, but before he could navigate away, a clickable “?” appeared above the word, successfully tempting him to click it for a definition, rather than looking for it elsewhere.
You can try this feature on any article on the NYT site (try this one?), and while it isn’t perfect (it opens a new window, for shame), it’s a great little example of how to take advantage of habitual user behaviour to reveal features at the exact moment when they’re needed.
Unfortunately this then leads to the perhaps more difficult question of figuring out what the habits of your users are (if they exist!) – I refuse to ruin any hopes I have of keeping this short by discussing this here, so this is left as an exercise for the reader.

Is there a good name for this idea?

I really don’t want to have to call it user-habits-as-unhide-hints, which is the best I have so far. Further examples of this sort of technique would be good, too!