栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++右值引用、移动语义和完美转发

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++右值引用、移动语义和完美转发

右值引用

左值(lvalue, left value),顾名思义就是赋值符号左边的值。准确来说, 左值是表达式(不一定是赋值表达式)后依然存在的持久对象。

右值(rvalue, right value),右边的值,是指表达式结束后就不再存在的临时对象。
纯右值(prvalue, pure rvalue),纯粹的右值,要么是纯粹的字面量,例如 10, true; 要么是求值结果相当于字面量或匿名临时对象,例如 1+2。非引用返回的临时变量、运算表达式产生的临时变量、 原始字面量、Lambda 表达式都属于纯右值。
将亡值(xvalue, expiring value),是 C++11 为了引入右值引用而提出的概念(因此在传统 C++ 中, 纯右值和右值是同一个概念),也就是即将被销毁、却能够被移动的值。

概述:引用的本质是别名,可以通过别名修改变量的值,转参时传引用避免拷贝。

  • 左值引用:指向左值,不能指向右值的引用。const左值引用可以指向右值。
int main() {
  int a = 5;          // a是个左值
  int &ref_a_left = a;// 左值引用指向左值
  const int &ref_left = 5; // const左值引用可以指向右值
  cout << ref_a_left << endl; // 5
  cout << a; // 5
}
  • 右值引用:指向右值,不能指向左值。
int main() {
  int &&lref = 5;
  // int &&lref2 = lref; 
  // lref拥有名称,是有地址的,是左值。
}
  • 被声明出来的左、右值应用都是左值。

  • 函数参数:

#include 

using namespace std;

int change(int &&a) {
  a = 10;
  return a;
}

int change2(int &a) {
  a = 10;
  return a;
}

int change3(int a) {
  a = 10;
  return a;
}

int main() {
  int &&rref = 5;
  int ref = 5;
  int &lref = ref;

  // 测试右值引用
  // cout< 
移动语义 

概述:各种情况下对象的资源所有权转移问题。

解决的场景:

  1. 按值传入参数
  • 如果使用const string& name作为参数,就会调用一次构造函数和移动构造函数。
class person {
public:
  person (string name) 
  : name_(move(name))
  {
  }
  string name_;
};

person p("Alice");

string bn = "Bob";
person p1(bn); 
  • 显式移动构造,将传入的字符串移入成员变量。
  1. 按值返回
vector test() {
  vector v;
  return v;
}

编译成:

std::vector > test()
{
  vector v = std::vector >() ;
  return std::vector >(static_cast > &&>(v));
}
  1. 接收右值表达式
    优化表达式的值初始化对象或者给对象复制的性能。现在函数直接利用这些右值。
完美转发

std::forward成为完美转发,即经过转发的值的属性不变。没有完美转发的情况下,经过函数传参使得右值转为左值。

#include 
using namespace std;

void print(int &a) {
  cout << "左值" << endl;
}

void print(int &&a) {
  cout << "右值" << endl;
}

template
void test(X &&x) {
  print(x);
  print(std::forward(x));
  print(std::move(x));
}

int main(int argc, char *argv[]) {
  int a = 10;
  test(a);
  cout << "============" << endl;
  test(10);
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/352554.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号