14

I see lots of people having problems understanding rvalue references. Will "ordinary" C++ code (e.g., that uses the standard library, but doesn't implement it) need to know about rvalue references once the new standard comes out, or can the people/code just pretend rvalue references don't exist? Do rvalue references primarily concern library implementors or all programmers?

Xeo
  • 129,499
  • 52
  • 291
  • 397
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • would CW be appropriate for this? – Johannes Schaub - litb Nov 13 '10 at 17:34
  • What is an "ordinary" C++ programmer? – John Dibling Nov 13 '10 at 17:36
  • @John: I would consider someone *using* the STL an "ordinary" programmer, and someone *implementing* the STL not ;) – fredoverflow Nov 13 '10 at 17:38
  • 1
    For the most part, CW is no more. Rather than moving to PSE.com, I'd think about a minor rephrasing, something like "What (kinds of) code will *need* to use rvaule-references?" Regardless of the wording, I think it really is pretty much directly about code and programming. – Jerry Coffin Nov 13 '10 at 17:40
  • @Johannes: [CW is dead](http://meta.stackexchange.com/questions/392/should-the-community-wiki-police-be-shut-down/7183#7183). – sbi Nov 13 '10 at 17:44
  • @Jerry: Why don't you go ahead and make the changes? – sbi Nov 13 '10 at 17:44
  • 1
    @John: An "ordinary C++ programmer" is one who says "template class", can't tell FTPS from overloading, and hasn't heard of move semantics. There's millions of them out there. In fact, there's thousands of them _here_ on SO. – sbi Nov 13 '10 at 17:48
  • @sbi: done. To answer the question directly, because in most editing, I stick to fixing things like unformatted code or obvious typos, where I'm pretty sure there's no chance I might accidentally change the original intent. – Jerry Coffin Nov 13 '10 at 17:49
  • @Jerry Yeah, me too, but I wouldn't want this one to get closed by ... [deleted, lest this gets flagged for obscenity] – sbi Nov 13 '10 at 17:51
  • 3
    I'm biased and naturally grumpy about such things, but I've always been of the opinion that no C++ programmer *should* be "ordinary" in the sense that they don't really know what they are doing. Any hack can write a Java or VB program by just banging on the keyboard. C++ programmers are -- or should be -- special. – John Dibling Nov 13 '10 at 17:56
  • 2
    @John: Note that you wrote "should"? I fully agree to that. – sbi Nov 13 '10 at 17:58
  • 2
    @John: I quite agree -- but one of the real strengths of C++ (IMO) is having a fairly smooth transition from beginner to expert, unlike some languages that (for example) reserve some features to those who develop the language itself. – Jerry Coffin Nov 13 '10 at 18:03
  • @Johannes: why programmers? It fits there no better than here. – peterchen Nov 13 '10 at 18:56
  • @Johannes: See the first comment, by Marcel. – sbi Nov 14 '10 at 21:07
  • Err, sorry, Johannes, mixed up the commeters, it was @Marcel... – peterchen Nov 15 '10 at 13:39

8 Answers8

6

I didn't see anything much to disagree with in GMan's (aka gmannickg) blog article on the subject:

http://blackninjagames.com/?p=95

Summary: anyone who knows about copy-and-swap (and in general the rule of three), should know about move semantics (and hence rvalue references), because the best-practice idioms change as a result. I think, therefore, that's anyone who cares at all about C++.

I don't think you have to know, because of course copy-and-swap still works, it's still exception-safe, and so on. And I suppose someone could argue whether "ordinary" C++ code and programmers even need to know copy-and-swap. I'd hope that the answer is "well, duh, obviously", but you never know.

Of course, the point at which one can start using C++0x will vary from place to place. It's probably not a good idea to unlearn C++03 any time soon.

For example, returning huge collections by value in contexts that aren't valid for copy elision becomes a better bet if you can rely on move assignment. This isn't a case of something that's invalid in C++03 becoming valid in C++0x, it's code that's heinously slow in C++03, that you'd work around (even if only with a well-placed swap), becoming fine in C++0x. So if you pretend rvalue references don't exist, you'll carry on working around something you don't need to. If you make the jump then it might backport cleanly to C++03 but run dog-slow, which is a pain.

So the smart thing might be to know about it, and in many contexts pretend it doesn't exist.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Hmm, the link doesn't seem fixable. GMan's old blog is gone and not archived anywhere I can find. I'll leave the link in case it helps anyone find the post. – Steve Jessop Jun 10 '12 at 19:18
  • @SteveJessop: Ah, bugger. Do you remember what this linked to? Is [this](http://www.gmannickg.com/?p=17) the correct replacement? – GManNickG Sep 06 '12 at 05:12
  • @GManNickG: I think that's a reasonable replacement, but IIRC (from nearly 2 years go) it's not the same article I originally linked to. I think the one from before discussed Rule of 3 -> Rule of 4 in general, whereas this one is specifically about `operator=` and copy-and-swap with a C++11 bit at the end. – Steve Jessop Sep 06 '12 at 08:24
  • @SteveJessop: Hm, it's probably bad I can't remember. :) Oh well. – GManNickG Sep 06 '12 at 15:51
  • Let's just assume that you wrote a jolly good article which addresses copy-and-swap, and demonstrates that C++11 programmers will want to know how to use rvalue references to give their classes move semantics. Maybe it was this article I read at the time, maybe you wrote another one as well. Maybe both, and the one I'm half-remembering now isn't the one I linked to then! – Steve Jessop Sep 06 '12 at 15:59
5

At least for most situations, you can ignore them for about as long as you feel like you want to. (Re)writing the standard library to use them allows considerable optimization and some new capabilities, but one of the major goals is that existing code should continue to work just fine (though, in some cases, faster).

Supporting existing code implies that anybody who feels like it can continue to write code the same way they would have previously, and not be affected either (again, except that some library "stuff" they use might be faster).

At the same time, there are some pretty good reasons somebody might want to learn at least a few rules of thumb that let them make some simple use of rvalue-references. One obvious example would be a problem people run into regularly now: they have a class that it doesn't really make sense to copy objects, but they'd still like to be able to put those objects in a collection (e.g., a vector).

They can do that by making objects of that class movable but not copyable. A prime example of this would be streams -- right now, you can't put any kind of iostream object into a collection, but in C++0x you will be able to.

Another possibility is to use "perfect forwarding". This can make it quite a bit easier to consolidate what would previously have been a number of separate functions into one with really trivial front-ends that all forward to the one that does the real work. You can always do without this, but in some cases it can make the code quite a bit less repetitious.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
3

Most people can just pretend that they don't exist, and they'll just see the benefits (faster code in some cases).

Remember that C++0x is going to be 99.9% backwards compatible, so all existing code will still work, meaning that you can continue to write C++0x code as if it were C++03.

If you want to reap the benefits of rvalue references then of course you'll need to learn about them, but most of the time that will only be a concern of library writers.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
3

You may not need to know about rvalue references in the sense of writing some function that takes one, but you may benefit from understanding move semantics, from knowing what a move constructor is, and so on. If you want to use unique_ptr (and gain the perf benefit since it has no reference counting) then you will almost certainly need to use std::move (say, into and out of a collection) and I can't imagine approaching that in the "what if I put a & or a * here?" way that a typical second-year student copes with pointers.

I just did a "what's new in VC++ featuring C++0x" talk at Tech Ed Europe in Berlin that had one slide on rvalue references and I basically said "you need to know that these are here because they make the STL way faster" but I didn't drill any further. That seemed to be better accepted by the attendees than the (longer) variants I have had in other talks.

Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
  • 1
    Can we see the slides to (or even a video of) that talk somewhere on the web? – fredoverflow Nov 13 '10 at 18:00
  • The problem is that all those "ordinary" programmer know about rvalue references after your slide is that they need to know about them. (I've seen a full-blown presentation of them by Scott Meyers, and I can see that this will take _very_ long to sink in for most C++ programmers, even when presented as well as done by Scott.) – sbi Nov 13 '10 at 18:01
  • 2
    Ask and you shall receive: http://www.msteched.com/2010/Europe/DEV311 has low and high WMV and the ppts. I haven't watched the video yet but the talk was rated #4 in the whole conference so many people liked it. – Kate Gregory Nov 13 '10 at 18:02
  • @sbi - and they can drill in when they need to. Some will say "actually I don't mind the ref counting overhead anyway" :-). – Kate Gregory Nov 13 '10 at 18:04
  • @Kate: No, they _could_. Sadly, many never do. And if they don't drill into what move semantics are all about, how would they ever know when they'd need to understand them?) – sbi Nov 13 '10 at 19:41
  • @Kate: For what it's worth, I liked the talk, even though it wasn't "about" rvalue references. – fredoverflow Nov 13 '10 at 19:54
2

I agree, that RValue References are not everyones cup of tea -- the cup is quite big.

Because of this I tell learners of C++0x that the best approach to get started and to take advantage of RValue References is to use the STL and embrace its design patterns over time. It is very likely that by this you benefit from RValue References without understanding them completely beforehand.

towi
  • 21,587
  • 28
  • 106
  • 187
1

In c++11 I would pass anything that I plan on 'storing' or 'consuming' by &&. This results in the most efficient code, but 'breaks' lvalue compatibility and forces me to consider having two (or more) versions of every method. Unfortunately, you get a explosion of permutations of rvalue and const& as the number of arguments increases and it makes getting function pointers much more 'ugly'.

Instead of providing two (or more) overloads, one for lvalues and one for rvalue, I have decided to only provide the rvalue overload and if the user wants to pass an lvalue they wrap with std::ref(), std::cref(), std::move() or my own helper copy() which makes the copy explicit and converts the lvalue to a rvalue. (std::ref() and std::cref() could only work if the arguments are template parameters... in which case the method would probably use std::forward<>() to handle the auto-detection of move vs copy semantics.

template<typename T>
T copy( const T& v ) { return v; }

If I am writing a method that does not 'store' or 'consume' the input then I use const&

I should probably clarify, that I would use const& for any types that do not benefit from move semantics (no deep copies). But when you are writing template code, you do not want to make that assumption about the type.

Another practice I am considering is making certain classes 'explicit copy only'.

class test  {
  public:
    test(){...};
    test( test&& t ){...}

  private:
    template<typename T>
    friend T copy(const T&t);

    test& operator=(const test&); // not implemented
    test( const test& t ){...}

    std::vector<char> large_data;
};

int main( int argc, char** argv ) {
  test x;
  test y = copy(x);
  test z = x; // error, test(const test&) is private...
  return 0;
}

I would use this for any class that contains any 'movable members', such a strings, vectors, maps, etc. Technically there is no reason why I couldn't copy them, but why shouldn't I attempt move semantics everywhere possible unless I really do want to copy? With implicit copies there is no way for the compiler to warn me that I am doing something potentially expensive.

bytemaster
  • 572
  • 2
  • 5
1

Scott Meyers divided C++0x features into:

  1. Features for everybody.
  2. Features for Class authors.
  3. Features for Library authors.

RValues are definitely Library authors.

ManicQin
  • 159
  • 1
  • 8
  • I took it from his C++0x lecture notes, but you made me look again and I had a mistake: RValue refernces are under "features for Class authors" and "... library authors" – ManicQin Nov 14 '10 at 16:24
0

If you're not implementing a value-semantics class, you don't really need to know.

Edit: Or perfect forwarding. But that's similarly mostly a library use.

Puppy
  • 144,682
  • 38
  • 256
  • 465