What is std::move(), and when should it be used?

后端 未结 8 1961
粉色の甜心
粉色の甜心 2020-11-22 08:27
  1. What is it?
  2. What does it do?
  3. When should it be used?

Good links are appreciated.

相关标签:
8条回答
  • 2020-11-22 08:59

    1. "What is it?"

    While std::move() is technically a function - I would say it isn't really a function. It's sort of a converter between ways the compiler considers an expression's value.

    2. "What does it do?"

    The first thing to note is that std::move() doesn't actually move anything. It changes an expression from being an lvalue (such as a named variable) to being an xvalue. An xvalue tells the compiler:

    You can plunder me, move anything I'm holding and use it elsewhere (since I'm going to be destroyed soon anyway)".

    in other words, when you use std::move(x), you're allowing the compiler to cannibalize x. Thus if x has, say, its own buffer in memory - after std::move()ing the compiler can have another object own it instead.

    You can also move from a prvalue (such as a temporary you're passing around), but this is rarely useful.

    3. "When should it be used?"

    Another way to ask this question is "What would I cannibalize an existing object's resources for?" well, if you're writing application code, you would probably not be messing around a lot with temporary objects created by the compiler. So mainly you would do this in places like constructors, operator methods, standard-library-algorithm-like functions etc. where objects get created and destroyed automagically a lot. Of course, that's just a rule of thumb.

    A typical use is 'moving' resources from one object to another instead of copying. @Guillaume links to this page which has a straightforward short example: swapping two objects with less copying.

    template <class T>
    swap(T& a, T& b) {
        T tmp(a);   // we now have two copies of a
        a = b;      // we now have two copies of b (+ discarded a copy of a)
        b = tmp;    // we now have two copies of tmp (+ discarded a copy of b)
    }
    

    using move allows you to swap the resources instead of copying them around:

    template <class T>
    swap(T& a, T& b) {
        T tmp(std::move(a));
        a = std::move(b);   
        b = std::move(tmp);
    }
    

    Think of what happens when T is, say, vector<int> of size n. In the first version you read and write 3*n elements, in the second version you basically read and write just the 3 pointers to the vectors' buffers, plus the 3 buffers' sizes. Of course, class T needs to know how to do the moving; your class should have a move-assignment operator and a move-constructor for class T for this to work.

    0 讨论(0)
  • 2020-11-22 09:00

    std::move itself does nothing rather than a static_cast. According to cppreference.com

    It is exactly equivalent to a static_cast to an rvalue reference type.

    Thus, it depends on the type of the variable you assign to after the move, if the type has constructors or assign operators that takes a rvalue parameter, it may or may not steal the content of the original variable, so, it may leave the original variable to be in an unspecified state:

    Unless otherwise specified, all standard library objects that have been moved from being placed in a valid but unspecified state.

    Because there is no special move constructor or move assign operator for built-in literal types such as integers and raw pointers, so, it will be just a simple copy for these types.

    0 讨论(0)
提交回复
热议问题