I think it's more a question of philosophy than technic :)
The underlying question is what is the difference between Move and Copy. I won't jump into technical / standardista language, let's do it simply:
- Copy: create another identical object (or at least, one which SHOULD compare equal)
- Move: take an object and put it in another location
As you said, it is possible to implement Move in term of Copy: create a copy into the new location and discard the original. However there are two issues there. One is of performance, the second is about objects used for RAII: which of the two should have ownership ?
A proper Move constructor solves the 2 issues:
- It is clear which object has ownership: the new one, since the original will be discarded
- It is thus unnecessary to copy the resources pointed to, which allows for greater efficiency
The auto_ptr
and unique_ptr
are a very good illustration of this.
With an auto_ptr
you have a screwed Copy semantic: the original and the copy don't compare equal. You could use it for its Move semantic but there is a risk that you'll lose the object pointed to somewhere.
On the other hand, the unique_ptr
is exactly that: it guarantees a unique owner of the resource, thus avoiding copying and the inevitable deletion issue that would follow. And the no-copy is guaranteed at compile-time too. Therefore, it's suitable in containers as long as you don't try to have copy initialization.
typedef std::unique_ptr<int> unique_t;
typedef std::vector< unique_t > vector_t;
vector_t vec1; // fine
vector_t vec2(5, unique_t(new Foo)); // Error (Copy)
vector_t vec3(vec1.begin(), vec1.end()); // Error (Copy)
vector_t vec3(make_move_iterator(vec1.begin()), make_move_iterator(vec1.end()));
// Courtesy of sehe
std::sort(vec1.begin(), vec1.end()); // fine, because using Move Assignment Operator
std::copy(vec1.begin(), vec1.end(), std::back_inserter(vec2)); // Error (copy)
So you can use unique_ptr
in a container (unlike auto_ptr
), but a number of operations will be impossible because they involve copying which the type does not support.
Unfortunately Visual Studio may be quite lax in the enforcement of the standard and also has a number of extensions that you would need to disable to ensure portability of the code... don't use it to check the standard :)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…