I think this is more a matter of philosophy than technology :)
The main question is the difference between Move and Copy. I will not delve into the technical / standardized language, let's do it simply:
- Copy: create another identical object (or at least one that MUST be equal to equal)
- Move: take an object and place it in another place
As you said, it is possible to implement Move in the terms of Copy: create a copy in a new place and discard the original. However, there are two questions. One of them has performance, the second - objects used for RAII: which of the two should have ownership?
The proper Move constructor solves two issues:
- It is clear which property has the property: new, as the original will be discarded
- Thus, there is no need to copy the specified resources, which improves efficiency
The characters auto_ptr and unique_ptr are a very good illustration of this.
With auto_ptr , you have screwed-up copy semantics: the original and the copy are not compared the same. You can use it for semantics of Move, but there is a risk that you will lose the object that it points to somewhere.
unique_ptr , unique_ptr other hand, is exactly what: it guarantees the unique owner of the resource, which avoids copying and the inevitable delete problem that will follow. And without copies, compilation time is guaranteed. Therefore, it is suitable in containers if you are not trying to initialize a copy.
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)
Thus, you can use unique_ptr in the container (unlike auto_ptr ), but a number of operations will be impossible, since they involve copying, which the type does not support.
Unfortunately, Visual Studio can be quite weak in applying the standard, and it also has a number of extensions that you need to disable to ensure code portability ... do not use it to verify the standard :)