What is std :: move (), When should you use?

  1. What is it?
  2. What does it do?
  3. When should you use?

We appreciate the good links.


#1st Floor

When you need at the content elsewhere "transport" an object, you can use the move, without having to copy (ie content does not repeat, which is why it can be used for certain objects can not be copied, such as unique_ptr). Obtain a temporary object content when using std :: move, objects can not be copied (and save a lot of time).

This link really helped me:

http://thbecker.net/articles/rvalue_references/section_01.html

If my answer came too late, I'm sorry, but I'm also looking for good links std :: move, I found the link above somewhat "serious."

This emphasizes the r value of the reference, you should use them in any case, I consider it in more detail, which is why I wanted to share this link.


#2nd Floor

std :: move itself does not do much. I think it calls a constructor function for a mobile object, but it is actually only performs a type conversion (converted to a value of the variable a rvalue left, so that the variable can be passed as a parameter to a mobile constructor or assignment operator ).

Thus std :: move merely as a precursor to movement using semantics. Process is an effective way of temporary objects moving semantic nature.

Consider the objectA = B + C + D + E + F;

This is a beautiful code, but E + F produces a temporary object. Then D + temp produce another temporary objects, and so on. In each of the general category of "+" operator, the copy will appear dark.

E.g

Object Object::operator+ (const Object& rhs) {
    Object temp (*this);
    // logic for adding
    return temp;
}

Create a temporary object in this function is useless - when these temporary objects out of range, they will delete the end of the line.

We prefer to use move semantics "predatory" temporary objects and perform similar operations

 Object& Object::operator+ (Object&& rhs) {
     // logic to modify rhs directly
     return rhs;
 }

This avoids unnecessary deep copies. Referring to the example, only part of the depth of replication occurs is now used in the rest E + F. move semantics. Need for mobile constructor or assignment operator to assign the result to A.


#3rd floor

"What is it?"

Although std::move()a function technically - I would say it is not a real function . It is between the value of the expression compiler consider ways conversion device.

"It did what?"

First thing to note is std::move() not actually move anything . It expressions from left value (such as naming variables) is converted to the value of x . xvalue tells the compiler:

You can plunder me move everything I own and use it in other places (because I will soon be destroyed). "

In other words, when you use std::move(x), you allow the compiler to erode x. Therefore, if xthere is own buffer in memory - the std::move()compiler can make another object owns it.

You can also from a prvalue mobile (such as temporary value you are passing), but this is rarely useful.

"When should I use?"

Another way of asking this question is "What I would object existing resources?" Well, if you are writing your application code, you may not be temporary objects created by the compiler extensive treatment. Therefore, the main place to do this is a function of the constructor, operator method, similar to the standard library algorithms, etc., where the object is automatically created and destroyed a lot. Of course, this is just a rule of thumb.

A typical use of resources from one object is to "move" to another object instead of copying. @Guillaume link to this page , which has a simple short example: using less copy and switch two objects.

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)
}

Use move allows you to exchange resources instead of copying them:

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

Think about when T n is the size of vector<int>the time what happens. In the first version, you read and write elements 3 * n, in the second version, you read and write substantially only three vector buffer pointers. Of course, we need to know how T stage moves; you should have a class assignment operator and a mobile T constructor class of mobile, so that it can work.


#4th floor

C ++ 11 R on the reference value and the moving constructor Wikipedia page

  1. 11 in C ++, except from the copy constructor, an object can have moved constructors.
    (Except copy assignment operator, they have moved the assignment operator.)
  2. If the object has a type "rvalue-Reference" ( Type &&), is used instead of the mobile constructor copy constructor.
  3. std::move()It is a converter that generates an object rvalue references to move therefrom.

This is a way to avoid copy of the new C ++ method. For example, using a mobile constructor, std::vectorcan replicate its internal pointer to the new object, the moving object remains incorrect state, thereby avoiding all data is copied. This will be the C ++ - effective.

Try Google search move semantics, the right value, perfect forwarding.


#5th Floor

Q: What is std::move?

A: std::move()it is a function of the value converted into the right reference for the C ++ standard library.

Simply put std::move(t)the equivalent of:

static_cast<T&&>(t);

rvalue is a temporary value that does not exceed its defined expressions, for example, never store intermediate results in a variable function.

int a = 3; // 3 is a rvalue, does not exist after expression is evaluated
int b = a; // a is a lvalue, keeps existing after expression is evaluated

In the N2027 in the given std :: move () the realization: "Rvalue References Introduction" as follows:

template <class T>
typename remove_reference<T>::type&&
std::move(T&& a)
{
    return a;
}

As you can see, regardless of whether the value T( ), reference type ( T&) or rvalue references ( T&&) call std::movereturns T&&.

Q: What does it do?

A: As an actor, it does not do anything at runtime. Only at compile time to tell the compiler that you want to continue to be treated as right reference value.

foo(3 * 5); // obviously, you are calling foo with a temporary (rvalue)

int a = 3 * 5;
foo(a);     // how to tell the compiler to treat `a` as an rvalue?
foo(std::move(a)); // will call `foo(int&& a)` rather than `foo(int a)` or `foo(int& a)`

It does not do:

  • Copy parameters
  • Call the copy constructor
  • Change parameter object

Q: When should I use?

A: If you want to call the function support move semantics, and the argument is not rvalue (temporary expressions) should be used std::move.

This raises the following follow-up questions for me:

  • What is the move semantics? Compared with the copy semantics, move semantics is a programming technique in which by "take over" another member instead of copying the object to initialize the object's member. This "take over" can only be achieved through a pointer and a resource handle, which can be cheaper transferred by copying integer pointer or handle and not the underlying data.

  • What kind of support for classes and objects move semantics? As a developer, you can implement move semantics in their class, if they will transfer their members rather than copying them to benefit. Once realized the move semantics, you will directly benefit from many libraries programmers work, they've added support classes have moved semantics for efficient processing.

  • Why does the compiler can not figure out yourself? Unless you say otherwise, the compiler can not simply call another function overloading. You must help the compiler selection function should be called conventional or mobile version.

  • In any case, I want to tell the compiler that it should be variable as the right value? This is likely to happen in the template or library function, you know you can save intermediate results.


#6th floor

"What is it?" And "what it does?" Has been explained above.

I will illustrate "When should I use."

For example, we have a class that contains a large array of resources.

class ResHeavy{ //  ResHeavy means heavy resource
    public:
        ResHeavy(int len=10):_upInt(new int[len]),_len(len){
            cout<<"default ctor"<<endl;
        }

        ResHeavy(const ResHeavy& rhs):_upInt(new int[rhs._len]),_len(rhs._len){
            cout<<"copy ctor"<<endl;
        }

        ResHeavy& operator=(const ResHeavy& rhs){
            _upInt.reset(new int[rhs._len]);
            _len = rhs._len;
            cout<<"operator= ctor"<<endl;
        }

        ResHeavy(ResHeavy&& rhs){
            _upInt = std::move(rhs._upInt);
            _len = rhs._len;
            rhs._len = 0;
            cout<<"move ctor"<<endl;
        }

    // check array valid
    bool is_up_valid(){
        return _upInt != nullptr;
    }

    private:
        std::unique_ptr<int[]> _upInt; // heavy array resource
        int _len; // length of int array
};

Test code:

void test_std_move2(){
    ResHeavy rh; // only one int[]
    // operator rh

    // after some operator of rh, it becomes no-use
    // transform it to other object
    ResHeavy rh2 = std::move(rh); // rh becomes invalid

    // show rh, rh2 it valid
    if(rh.is_up_valid())
        cout<<"rh valid"<<endl;
    else
        cout<<"rh invalid"<<endl;

    if(rh2.is_up_valid())
        cout<<"rh2 valid"<<endl;
    else
        cout<<"rh2 invalid"<<endl;

    // new ResHeavy object, created by copy ctor
    ResHeavy rh3(rh2);  // two copy of int[]

    if(rh3.is_up_valid())
        cout<<"rh3 valid"<<endl;
    else
        cout<<"rh3 invalid"<<endl;
}

Output is as follows:

default ctor
move ctor
rh invalid
rh2 valid
copy ctor
rh3 valid

We can see that std::movewith move constructoreasily achieve the conversion of resources.

Where else std::moveuseful?

When the elements of the array to sort, std::moveit is also useful. Many sorting algorithms (e.g., selection sort and bubble sort) to work by switching elements. Previously, we had to resort to copy semantics to be exchanged. Now we can use move semantics, which is more effective.

If we want to move the contents of a smart pointer management to another smart pointer, it will be useful.

lead:

Original articles published 0 · won praise 0 · Views 2229

Guess you like

Origin blog.csdn.net/p15097962069/article/details/103904326