ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

[C++] C++11新特性之左值右值、左值引用右值引用、mov、forward

2021-08-06 14:05:48  阅读:141  来源: 互联网

标签:右值 int 绑定 左值 C++ 引用 &&


参考

左值右值

C++的表达式要么是左值,要么是右值。

简单说,左值可以位于赋值语句的左边,右值则不能。

  • 右值:当一个对象被用作右值的时候,用的是对象的值(内容),右值要么是字面常量,要么在表达式求值过程中创建的临时对象,没有名字,不能被赋值。
  • 左值:当一个对象被用作左值的时候,用的是对象的身份(在内存中的位置),左值就是有名字的对象,可以被赋值,左值可以被取地址,左值持久
  • 需要右值的地方可以用左值来代替,不能把右值当成左值使用,当左值当成右值使用的时候,实际上使用的是它的内容(值)

需要用到左值

  • 赋值运算符需要一个(非常量)左值作为其左侧运算对象,得到的结果仍然是一个左值
  • 取地址符作用于一个左值运算对象,返回指向该运算对象的指针,这个指针是一个右值
  • 内置解引用运算符、下标运算符、迭代器解引用运算符、string和vector的下标运算符求值结果都是左值
  • 内置类型和迭代器的递增递减运算符作用于左值运算对象,前置版本作用的和得到的都是左值

左值引用右值引用

#include <iostream>

//函数重载,形参为左值引用,接受左值
void process_value(int& i) { 
  std::cout << "LValue processed: " << i << std::endl; 
} 

//函数重载,形参为右值引用,接受右值
void process_value(int&& i) { 
  std::cout << "RValue processed: " << i << std::endl; 
} 

int main() { 
  int a = 0; 
  process_value(a);//传入左值,输出:LValue processed: 0
  process_value(1);//传入右值,输出1:RValue processed: 1
}
  • 左值引用&:不能将一个左值引用绑定到要求转换的表达式、字面常量或者返回右值的表达式

  • 右值引用&&:某个对象的另一个名字,可以将一个右值引用绑定到要求转换的表达式、字面常量或者返回右值的表达式,不能将右值引用直接绑定到一个左值上,右值引用指向将要被销毁的对象,用右值引用接管所引用的对象的资源

    int i = 1;
    int &&p = i;//错误,不能将一个右值引用绑定到一个左值上
    int &q = i * 22;//错误,不能将左值引用绑定到返回右值的表达式,i * 22是一个右值
    int &&q2 = i * 22;//正确,右值引用可以绑定到乘法右值结果上
    
  • 可以把左值引用绑定到返回左值的表达式(返回左值引用的函数、赋值、下标、解引用、前置递增递减运算符

    int i = 1;
    int &r = i;//正确,左值引用
    
  • 可以把const左值引用或者右值引用绑定到返回右值的表达式(返回非引用类型的函数、算术、关系、位、后置递增递减运算符

    const int &q1 = i * 22;//正确,可以将const引用绑定到右值
    
  • p是右值引用,指向一个右值,p本身是左值

    include <iostream>
    
    //函数重载,形参为左值引用,接受左值
    void process_value(int& i) { 
      std::cout << "LValue processed: " << i << std::endl; 
    } 
    
    //函数重载,形参为右值引用,接受右值
    void process_value(int&& i) { 
      std::cout << "RValue processed: "  << std::endl; 
    } 
    
    int main() { 
      int a = 0; 
      process_value(a);//输出:LValue processed: 0,说明传入的是左值
      int&& p = 3;
      process_value(p); //输出:LValue processed: 3,说明传入的是左值
    }
    //以上例子说明p是右值引用,指向一个右值,p本身是左值
    

    不能将一个右值引用绑定到一个右值引用类型的变量上

    变量是左值,不能将一个右值引用直接绑定到一个变量上

    int &&p = 11;//正确,字面常量是右值
    int &&q = p;//错误,p是左值
    
  • 右值引用的意义

    • 为临时变量续命,也就是为右值续命,因为右值在表达式结束后就消亡了,如果想继续使用右值,那就会动用昂贵的拷贝构造函数。

    • 右值引用是用来支持转移语义的。转移语义可以将资源 ( 堆,系统对象等 ) 从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,能够大幅度提高 C++ 的性能。

    • 转移语义是和拷贝语义相对的,可以类比文件的剪切与拷贝,当我们将文件从一个目录拷贝到另一个目录时,速度比剪切慢很多。

C++11 之move函数

头文件utility

使用move函数将获得一个绑定到左值上的右值引用类型

int &&p = 11;//正确,字面常量是右值
int &&q = p;//错误,p是左值
int &&q = std::move(p);//正确,move返回给定对象的右值引用

对于move不提供using声明,必须写成std::move,不能写成move

C++11 之forward

头文件utility

与move不同,forward必须通过显式模板实参来调用

forward返回该显式实参类型的右值引用,即forward返回的是T&&

template <typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2) {
    f(std::forward<T2>(t2), std::forward<T1>(t1));
}

//如果调用flip(g, i, 42),i将以int&类型传递给g,42将以int&&类型传递给g

标签:右值,int,绑定,左值,C++,引用,&&
来源: https://blog.csdn.net/wangmj_hdu/article/details/119453478

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有