右值引用与转移语义(C++11)

参考资料:

左值和右值定义:

C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值。通俗的 左值的定义就是非临时对象(可以取地址,有名字),那些可以在多条语句中使用的对象。所有的变量都满足这个定义,在多条代码中都可以使用,都是左值。 右值是指临时的对象,它们只在当前的语句中有效。请看下列示例 :

  1. 简单的赋值语句

如:int i = 0;

在这条语句中,i 是左值,0 是临时值,就是右值。在下面的代码中,i 可以被引用,0 就不可以了。立即数都是右值。

  1. 右值也可以出现在赋值表达式的左边,但是不能作为赋值的对象,因为右值只在当前语句有效,赋值没有意义。

如:((i>0) ? i : j) = 1;

在这个例子中,0 作为右值出现在了”=”的左边。但是赋值对象是 i 或者 j,都是左值。

在 C++11 之前,右值是不能被引用的,最大限度就是用常量引用绑定一个右值,如 :

const int &a = 1;

左值和右值的语法符号:

左值的声明符号为”&”, 为了和左值区分,右值的声明符号为”&&”。但是如果临时对象通过一个接受右值的函数传递给另一个函数时,就会变成左值,因为这个临时对象在传递过程中,变成了命名对象。

转移语义:

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

通过转移语义,临时对象中的资源能够转移其它的对象里。

在现有的 C++ 机制中,我们可以定义拷贝构造函数和赋值函数。要实现转移语义,需要定义转移构造函数,还可以定义转移赋值操作符。对于右值的拷贝和赋值会调用转移构造函数和转移赋值操作符。如果转移构造函数和转移拷贝操作符没有定义,那么就遵循现有的机制,拷贝构造函数和赋值操作符会被调用。

示例:

编译选项:g++ move.cpp -std=c++11 -fno-elide-constructors

其中-fno-elide-constructors 意思是:强制g++总是调用copy构造函数,即使在用临时对象初始化另一个同类型对象的时候。

标准库函数std::move

既然编译器只对右值引用才能调用转移构造函数和转移赋值函数,而所有命名对象都只能是左值引用,如果已知一个命名对象不再被使用而想对它调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用,怎么做呢?标准库提供了函数 std::move,这个函数以非常简单的方式将左值引用转换为右值引用。

示例:

Original: https://www.cnblogs.com/luosongchao/p/4104604.html
Author: 罗松超
Title: 右值引用与转移语义(C++11)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/536581/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 选择排序 C++实现

    实现思想: 1.寻找[i, n)区间里的最小值min ( i>= 0 ) 2.交换min和第i的数 ( i>= 0 ) #include #include using …

    C++ 2023年5月29日
    063
  • c++实训课

    程序一: include 程序二: include 程序三: include Original: https://www.cnblogs.com/duanqibo/p/164138…

    C++ 2023年5月29日
    059
  • c++中CreateEvent函数

    函数原型: HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL…

    C++ 2023年5月29日
    065
  • Prim算法(二)之 C++详解

    普里姆(Prim)算法,是用来求加权连通图的最小生成树的算法。 基本思想对于图G而言,V是所有顶点的集合;现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T存放…

    C++ 2023年5月29日
    062
  • 解决c++中delete后内存系统不回收

    一般new出来的内存,delete掉后。 此时如果看top内存没有减少,则可以使用下面函数让系统强制回收。 #include malloc_trim(0); Original: h…

    C++ 2023年5月29日
    090
  • C++函数模板template(模板函数)

    函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。 面向对象的继承和多态机制有效…

    C++ 2023年5月29日
    062
  • C++ 知识点

    知识点 说明 所谓的引用就是给变量取一个别名,使一块内存空间可以通过几个变量名来访问。声明引用类型的变量需要在变量名前加上符号&,并且必须指定初值,即被引用的变量。 C++…

    C++ 2023年5月29日
    055
  • 【面试攻略】C++面试-紫龙游戏

    2020-11-25-紫龙 1.const有哪些用法https://blog.csdn.net/htyurencaotang/article/details/9276743?utm…

    C++ 2023年5月29日
    065
  • EclipseC++学习笔记-10 warnings being treated as errors,,error: format ‘%u’ expects argument of type

    增加选项All Options增加-Wformat=0 本博客是个人工作中记录,遇到问题可以互相探讨,没有遇到的问题可能没有时间去特意研究,勿扰。另外建了几个QQ技术群:2、全栈技…

    C++ 2023年5月29日
    053
  • libj 0.8.2 发布,Java/JavaScript API 的 C++ 实现

    libj 0.8.2 增加了一些新的字符串相关的方法。 libj 是一个跨平台的运行库,相当于提供了类似 Java/JavaScript API。libj 的内存管理是自动的,基于…

    C++ 2023年5月29日
    051
  • C++:STL 标准模板库容器的使用

    一、简介 STL容器: –> STL:Standard Template Library 标准模板库。 –> 自动申请内容和释放内存,因此无需n…

    C++ 2023年5月29日
    060
  • c++调用tflite实战

    一,概述 深度学习模型在移动端的应用越来越多,tensorflow lite就是专门为tensorflow模型在移动端上线推断设计的框架。tensorflow 官方提供了不少cv的…

    C++ 2023年5月29日
    062
  • c++ 11新特性学习1

    static_assert 静态断言,特点是编译期的断言检查 assert 运行时期的断言检查 二者参数用法相同 Original: https://www.cnblogs.com…

    C++ 2023年5月29日
    070
  • Mac eclipse 编译、调试c++ 程序

    可以先安装个CDT插件: eclipse菜单 -> Help -> Install New Software… -> Work with (Add…..

    C++ 2023年5月29日
    061
  • 面向对象编程技术的总结和理解(c++)

    目录树 1.继承 1.1 基类成员在派生类中的访问属性 1.2继承时导致的二义性 1.3 多基继承 2.虚函数的多态 2.1虚函数的定义 2.2派生类中可以根据需要对虚函数进行重定…

    C++ 2023年5月29日
    046
  • (转)C/C++中计算程序运行时间

    以前经常听人提起如何计算程序运行时间,给出一系列函数,当时没有注意,随便选了clock()最简单的方式进行计算。等到真正需要检测程序性能提升了多少,才发现这里面有很多要注意的地方。…

    C++ 2023年5月29日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球