[C ++ 11] _ [primary] _ [Use std: move object resource]

Source: Internet
Author: User

[C ++ 11] _ [primary] _ [Use std: move object resource]
Scenario: When the C ++ standard library uses functions such as vector: push_back, the parameter objects are copied and even data is copied. this will cause additional Object Memory creation. The original intention was to put the parameter push_back in. C ++ 11 provides the std: move function to convert the left value to xrvalue, and the new push_back version also supports the & Parameter overload version, at this time, you can use the memory efficiently. this is not required for standard library objects of pointer type. note: std: move (t) indicates that the object t can be moved from. It allows efficient conversion from the t resource to the lvalue. note: The original value of a standard library object that supports the left value of moved from after moved is valid (normal analysis can be performed), but it is unspecified and can be understood as null data, however, the return value of other methods of this object is not necessarily 0, such as size (). therefore, it is best not to use the objects after moved from? (If you do not understand it correctly, please inform me) move itself and assign it to itself as undefined behavior.

std::vector
  
    v = {2, 3, 3};v = std::move(v); // undefined behavior
  

Std: the prototype of the move function.

/** *  @brief  Convert a value to an rvalue. *  @param  __t  A thing of arbitrary type. *  @return The parameter cast to an rvalue-reference to allow moving it.*/template
  
     constexpr typename std::remove_reference<_Tp>::type&&  move(_Tp&& __t) noexcept  { return static_cast
   
    ::type&&>(__t); }
   
  

The prototype of the struct remove_reference is to overload multiple struct templates to obtain the original type.

/// remove_referencetemplate
  
     struct remove_reference  { typedef _Tp   type; };template
   
      struct remove_reference<_Tp&>  { typedef _Tp   type; };template
    
       struct remove_reference<_Tp&&>  { typedef _Tp   type; };
    
   
  
Example

Here are two examples to illustrate std: move usage.

Example 1

-The original lvalue is transferred after being moved from, so it is an empty string.
-Extracted from cppreference

void TestSTLObject(){    std::string str = "Hello";    std::vector
  
    v;    // uses the push_back(const T&) overload, which means    // we'll incur the cost of copying str    v.push_back(str);    std::cout << "After copy, str is \"" << str << "\"\n";    // uses the rvalue reference push_back(T&&) overload,    // which means no strings will be copied; instead, the contents    // of str will be moved into the vector.  This is less    // expensive, but also means str might now be empty.    v.push_back(std::move(str));    std::cout << "After move, str is \"" << str << "\"\n";    std::cout << "The contents of the vector are \"" << v[0]                                         << "\", \"" << v[1] << "\"\n";}
  

Output:

After copy, str is "Hello"After move, str is ""The contents of the vector are "Hello", "Hello"
Example 2

-Custom class objects support the moved from operation. You need to implement the Move Constructors and Move Assignment Operators operation.

#include 
  
   #include 
   
    #include 
    
     #include 
     
      #include 
      
       class MemoryBlock{public: // Simple constructor that initializes the resource. explicit MemoryBlock(size_t length) : _length(length) , _data(new int[length]) { std::cout << "In MemoryBlock(size_t). length = " << _length << "." << std::endl; } // Destructor. ~MemoryBlock() { std::cout << "In ~MemoryBlock(). length = " << _length << "."; if (_data != nullptr) { std::cout << " Deleting resource."; // Delete the resource. delete[] _data; } std::cout << std::endl; } // Copy constructor. MemoryBlock(const MemoryBlock& other) : _length(other._length) , _data(new int[other._length]) { std::cout << "In MemoryBlock(const MemoryBlock&). length = " << other._length << ". Copying resource." << std::endl; std::copy(other._data, other._data + _length, _data); } // Copy assignment operator. MemoryBlock& operator=(const MemoryBlock& other) { std::cout << "In operator=(const MemoryBlock&). length = " << other._length << ". Copying resource." << std::endl; if (this != &other) { // Free the existing resource. delete[] _data; _length = other._length; _data = new int[_length]; std::copy(other._data, other._data + _length, _data); } return *this; } // Retrieves the length of the data resource. size_t Length() const { return _length; } // Move constructor. MemoryBlock(MemoryBlock&& other) : _data(nullptr) , _length(0) { std::cout << "In MemoryBlock(MemoryBlock&&). length = " << other._length << ". Moving resource." << std::endl; // Copy the data pointer and its length from the // source object. _data = other._data; _length = other._length; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other._data = nullptr; other._length = 0; } // Move assignment operator. MemoryBlock& operator=(MemoryBlock&& other) { std::cout << "In operator=(MemoryBlock&&). length = " << other._length << "." << std::endl; if (this != &other) { // Free the existing resource. delete[] _data; // Copy the data pointer and its length from the // source object. _data = other._data; _length = other._length; // Release the data pointer from the source object so that // the destructor does not free the memory multiple times. other._data = nullptr; other._length = 0; } return *this; }private: size_t _length; // The length of the resource. int* _data; // The resource.};void TestSTLObject(){ std::string str = "Hello"; std::vector
       
         v; // uses the push_back(const T&) overload, which means // we'll incur the cost of copying str v.push_back(str); std::cout << "After copy, str is \"" << str << "\"\n"; // uses the rvalue reference push_back(T&&) overload, // which means no strings will be copied; instead, the contents // of str will be moved into the vector. This is less // expensive, but also means str might now be empty. v.push_back(std::move(str)); std::cout << "After move, str is \"" << str << "\"\n"; std::cout << "The contents of the vector are \"" << v[0] << "\", \"" << v[1] << "\"\n";}void TestMyObjectWithoutUseMove(){ std::vector
        
          v; MemoryBlock mb1(25); // MemoryBlock mb2(75); // MemoryBlock mb3(50); v.push_back(mb1); //v.push_back(mb2); //v.insert(v.begin() + 1, mb3);}void TestMyObjectWithUseMove(){ std::vector
         
           v; MemoryBlock mb1(25); // MemoryBlock mb2(75); // MemoryBlock mb3(50); v.push_back(std::move(mb1)); //v.push_back(MemoryBlock(75)); //v.insert(v.begin() + 1, MemoryBlock(50));}int main(int argc, char const *argv[]){ //TestSTLObject(); TestMyObjectWithoutUseMove(); std::cout << "......................................." << std::endl; TestMyObjectWithUseMove(); return 0;}
         
        
       
      
     
    
   
  

Output:
1. Note that each object of the first function calls a copy constructor and creates one more object. The move operation only moves resources.
2. note: Even if push_back is the second object, the vector will move the first object. It is strange that if you remove the annotation, you will find that the resource is Moving many times, which is affected by the implementation of the vector, it is clear that the Move feature is a push_back parameter.
3. note: When multiple objects in vector push_back of g ++ 4.8.1 are optimized, vs is used to call the Move constructor, while g ++ is used to call the Copy constructor, you will find that the copy constructor will be called many times.

In MemoryBlock(size_t). length = 25.In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.In ~MemoryBlock(). length = 25. Deleting resource.In ~MemoryBlock(). length = 25. Deleting resource........................................In MemoryBlock(size_t). length = 25.In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.In ~MemoryBlock(). length = 0.In ~MemoryBlock(). length = 25. Deleting resource.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.