C++0x!

Mar 28, 2011 19:41

After helping 3M move Lava C.O.S. to a great new team in St. Paul, I've started work with someone new project which involves some C++ programming, this time with Visual Studio 2010, which includes several important C++0x features I had been introduced to in David Musser's Generic Programming course in grad school.

The most interesting (and at first baffling) is rvalue references. They have the dubious syntax of && but are not a reference to a reference (whatever that would mean); it is a special type of reference that at compile time is known to be basically an unnamed temporary. Having this distinction lets you do a number of interesting optimizations related to moving objects around; so-called move semantics.



Suppose a function has returned to you a std::vector, as in:

std::vector x = makeGiantVector();
Now, the compiler may be able to optimize that, but it can't always. When it can't you have to construct a new vector, copy every element from the temporary that was returned, then delete the memory of the temporary. Since std::vector is heap-allocated, you would like to have the above line act like this:

std::vector tmp;
makeGiantVectorByReference(tmp);
std::vector x;

std::swap(tmp, x);

That is, we want to be able to steal the memory used by the temporary rather than copy it only to delete it. C++0x does this by letting temporaries like the values returned from a function bind to an "rvalue reference", so std::vector can have a constructor that takes temporaries and steals the memory. This is safe because the compiler only gives you rvalue references to temporaries. The constructors look like this:

vector(const vector& v) {

_beg = new T[v.size()];
_end = _beg + v.size();

_endOfStorage = _end;
copy(v.begin(), v.end(), begin());
}

vector(vector&& v) :
_beg(v._beg),
_end(v._end),
_endOfStorage(v._endOfStorage)
{

if (this != &v) {
v._beg = NULL;

v._end = NULL;
v._endOfStorage = NULL;
}
}

You can also overload the assignment operator with an rvalue reference, of course.

This is a nice optimization. The neat part is that this one feature gives you the ability to move things:

std::vector x = foo();
std::vector y = bar();

...
y = static_cast&&>(x);

Now y contains what x did but we let x lose what it was holding in the process. That's ugly syntax, so the standard provides a function with much better syntax:

std::vector x = foo();
std::vector y = bar();

...
y = std::move(x);

More to come. In particular, auto_ptr is deprecated, long live unique_ptr, which is based on the above.

A good reference.

c++ cpp

Previous post Next post
Up