zoukankan      html  css  js  c++  java
  • C++11--右值引用(移动语义)

    /*##################################################################
     * 右值引用 (C++ 11)
     *     主要用于以下:
     *        1. 移动语义
     *        2. 完美传参 Perfect Forwarding
     */
    
    /*
     * 什么是右值引用?
     */
    
    int a = 5;
    int& b = a;   // b是左值引用,在C++ 03叫做引用
    
    int&& c       // c 右值引用
    
    
    void printInt(int& i) { cout << "lvalue reference: " << i << endl; }
    void printInt(int&& i) { cout << "rvalue reference: " << i << endl; } 
    
    int main() {
       int i = 1;
       printInt(i);   // 调用第1个printInt
       printInt(6);   // 调用第2个printInt
    
    
       printInt(std::move(i));   // i是左值,先调move(),再调第2个printInt
    }
    
    /* 
     * 函数签名: 
     *
     *    int和int&不区分
     *    int和int&&不区分
     *
     *    int&和int&&区分,也就是可以重载左值引用和右值引用两个
     */
    
    
    
    
    
    /* What's the big deal??? */
    
    class boVector {
       int size;
       string label;
       double* array;
     public:
    	boVector(const boVector& rhs) {  // 拷贝构造
          size = rhs.size; 
          array = new double[size];
          for (int i=0; i<size; i++) { array[i] = rhs.array[i]; }
       }
    //	boVector(const boVector&& rhs) {  // 移动构造
     //     size = rhs.size; 
      //    array = rhs.array;
     //     rhs.array = nullptr;
      // }
    };
    void foo_by_value(boVector v) { v.label = "Student's Ages"; }       //如果没有右值引用,需要很多不同版本的函数
    void foo_by_reference(boVector& v) { v.label = "Student's Ages"; }
    boVector createBoVector();  // Creates a boVector
    
    void main() {
       boVector reusable = createBoVector();
       foo_by_value(reusable);
       ...
       boVector tmp= createBoVector();
       foo_by_reference(tmp);
    }
    
    
    /* Notes:
    	boVector(const boVector&& rhs) {  // 移动构造
          size = rhs.size; 
          array =  rhs.array;
       }
    
       boVector reusable = createBoVector();
       foo(reusable);
    */
    
    
    
    // 练习:
    boVecotor b = createBoVector();
    
    // Approach 1: 
    void foo(boVector & v);
    foo(b);
    
    // Approach 2: 
    void foo(boVector && v);
    foo(std::move(b));
    
    // 问题:两种方法的相同点和不同点
    // 两者参数传递上都不需要深拷贝
    // 后者将所有权也传递, move后不能再使用
    
    
    
    /* 
     * Note 1: 右值引用最主要的使用地方是重载拷贝构造和拷贝赋值,得到移动语义
     */
    X& X::operator=(X const & rhs); 
    X& X::operator=(X&& rhs);
    
    
    /* Note 2: 所以得STL容器都实现了移动语义,这意味着:
     *    a. 只要切换到C++ 11,代码不做任何改变程序就能变快
     *    b. 使用值传递的频率更高了
     */
    
    vector<int> foo() { ...; return myvector; } //可以直接返回
    
    void goo(vector<int>& arg);   // 当需要使用参数将goo中处理之后的数据带回外面,需要用引用传递
    
    
    
    /* 移动构造:
     *    目的:避免不必要的深拷贝
     * 1. 当既需要传引用又需要传值得时候,移动构造很有用
     * 2. 移动构造允许你对移动对象那个部分进行细微的控制
     */ 
    
    
    
    // 陷阱:右值引用是一个右值么?
    
    	boVector(const boVector && rhs) {
    		cout << "Move constructor.
    ";
    		size = rhs.size;
          array = rhs.array;
          overload(rhs);
       }
    
       overload(boVector&  v) { cout << "by lvalue."; }
       overload(boVector&& v) { cout << "by rvalue."; }
    
    
  • 相关阅读:
    oracle 触发器的编写
    单例类与常见双下方法
    实现高效率的冒泡排序
    面向对象基础(五)
    面向对象基础(四)
    面向对象基础(三)
    面向对象基础(二)
    面向对象(基础)
    四指针法
    因数法
  • 原文地址:https://www.cnblogs.com/logchen/p/10193564.html
Copyright © 2011-2022 走看看