|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2002-02-04 16:26:23
On Monday, February 4, 2002, at 11:15 AM, Jeremy Siek wrote:
> On Sat, 2 Feb 2002, Mark Rodgers wrote:
>>
>> - Copy and assignment have auto_ptr sematics, i.e. use an
>> auto_vector_ref and clear the source object. I've
>> implemented this using swap, so passing and returning
>> auto_vectors by value is relatively cheap.
>
> This bother me a bit. From what I understand, all the other properties
> of
> auto_vector would still allow it to conform to the Standard Container
> requirements, but these copy and assignment semantics would break
> that...
Perhaps auto_vector would be a good place to experiment with "move
semantics".
Background:
It is my strongly held opinion that C++ has done a good job with copy
semantics, but has all but ignored the concept of move semantics which I
believe to be just as fundamental and important.
When dealing with scalars, there is no practical difference between move
and copy. Either act simply copies the value of the int (for example)
from one location to another. But when dealing with an object that owns
resources, an important distinction between move and copy can and should
be made:
T a;
T b = copy(a);
T c = move(a);
Please excuse the imaginary syntax for a moment. The second line
creates a new variable b which has the same value as a, and leaves a
unchanged. This is a classic copy, as we all know today. To achieve
this, any resources that a owns must be somehow replicated (or shared)
so that b now also owns (or shares ownership) of the resources as well.
However the 3rd line is different. c takes control of a's resources.
After the move, a is no longer the same. It has given up ownership of
all resources to c.
The concept of move semantics is crucial for high performance, exception
safe code.
For example, imagine inserting into the middle of a vector<string>. If
the vector could /move/ strings instead of copy them to make room in the
middle, both performance and exception safety would be greatly enhanced.
std::auto_ptr (and its authors) was a pioneer in this area. Like most
pioneers, it got some key concepts right. And like most pioneers,
auto_ptr is not perfect. Imho, the big thing it got wrong is that it
gave auto_ptr move semantics with copy syntax:
auto_ptr<int> a;
auto_ptr<int> b(a); // looks like copy, but it is a move
There should be nothing wrong or strange about having move semantics.
Just they need to not be confused with copy semantics. And not all
objects need support move semantics, just as today not all objects
support copy semantics (by deriving from boost::noncopyable for
example). Some objects (such as vector or string) could (and should)
support both copy semantics and move semantics. Objects such as
auto_ptr (or auto_vector) should only support move semantics, not copy.
What remains to be done is to settle on a uniform syntax for move
semantics. John Maddock has suggested:
T b = std::move(a);
Perhaps boost::auto_vector could experiment with this. The big
stumbling block I've had to date is allowing move from a temporary T,
but disallowing move from a const T, and packaging this up in a
relatively reusable package so that giving your class move semantics is
no harder than giving it copy semantics.
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk