class cannot_benefit_from_move_semantics{int a; // moving an int means copying an intfloat b; // moving a float means copying a floatdouble c; // moving a double means copying a doublechar d[64]; // moving a char array means copying a char array
// ...};
Implementing safe "move-only" types; that is, types for which copying does not make sense, but moving does. Examples include locks, file handles, and smart pointers with unique ownership semantics. Note: This answer discusses std::auto_ptr, a deprecated C++98 standard library template, which was replaced by std::unique_ptr in C++11. Intermediate C++ programmers are probably at least somewhat familiar with std::auto_ptr, and because of the "move semantics" it displays, it seems like a good starting point for discussing move semantics in C++11. YMMV.
What is a move?
The C++98 standard library offers a smart pointer with unique ownership semantics called std::auto_ptr<T>. In case you are unfamiliar with auto_ptr, its purpose is to guarantee that a dynamically allocated object is always released, even in the face of exceptions:
{std::auto_ptr<Shape> a(new Triangle);// ...// arbitrary code, could throw exceptions// ...} // <--- when a goes out of scope, the triangle is deleted automatically
auto_ptr的不同寻常之处在于它的“复制”行为:
auto_ptr<Shape> a(new Triangle);
+---------------+| triangle data |+---------------+^|||+-----|---+| +-|-+ |a | p | | | || +---+ |+---------+
auto_ptr<Shape> b(a);
+---------------+| triangle data |+---------------+^|+----------------------+|+---------+ +-----|---+| +---+ | | +-|-+ |a | p | | | b | p | | | || +---+ | | +---+ |+---------+ +---------+
unique_ptr<Shape> make_triangle(){return unique_ptr<Shape>(new Triangle);} \-----------------------------/|| temporary is moved into c|vunique_ptr<Shape> c(make_triangle());
也许令人惊讶的是,自动对象(未声明为static的局部变量)也可以隐含移出函数:
unique_ptr<Shape> make_square(){unique_ptr<Shape> result(new Square);return result; // note the missing std::move}
foo(make_triangle()); // T is unique_ptr<Shape>, T&& is unique_ptr<Shape>&&unique_ptr<Shape> a(new Triangle);foo(a); // T is unique_ptr<Shape>&, T&& is unique_ptr<Shape>&
class A{int i, *p;
public:// Movement of an object inside a copy constructor.A(const A& a) : i(a.i), p(a.p){a.p = nullptr; // pointer invalidated.}
~A() { delete p; }// Deleting NULL, 0 or nullptr (address 0x0) is safe.};