右值引用与转移语义(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++ typedef和#define的作用范围

    typedef: 如果放在所有函数之外,它的作用域就是从它定义开始直到文件尾; 如果放在某个函数内,定义域就是从定义开始直到该函数结尾; #define: 不管是在某个函数内,还是…

    C++ 2023年5月29日
    0101
  • C++20新特性

    conceptrequiresconstinitconstevalco_awaitco_returnco_yieldchar8_t 优点:1)没有头文件;2)声明实现仍然可分离, …

    C++ 2023年5月29日
    069
  • 客户端单元测试实践——C++篇

    作者 | 思兼来源 | 阿里开发者公众号 背景 我们团队在手淘中主要负责BehaviX模块,代码主要是一些逻辑功能,很少涉及到UI,为了减少双端不一致问题、提高性能,我们采用了将核…

    C++ 2023年5月29日
    070
  • C++设计模式(转载)

    C++设计模式之Adapter一、功能 将一个类的接口转换成客户希望的另外一个接口,解决两个已有接口之间不匹配的问题。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类…

    C++ 2023年5月29日
    087
  • C++ std::ofstream 和 std::ifstream

    简介 C++中对文件进行读写的。 使用Demo #include #include #include <string> #include <string.h&gt…

    C++ 2023年5月29日
    043
  • 拓扑排序(二)之 C++详解

    拓扑排序(Topological Order)是指,将一个有向无环图(Directed Acyclic Graph简称DAG)进行排序进而得到一个有序的线性序列。 这样说,可能理解…

    C++ 2023年5月29日
    049
  • C/C++标准新特性简介

    参考文档 C语言的起源发展 C语言诞生于1972年,美国贝尔实验室。作者为:Dennis MacAlistair Ritchie(丹尼斯·里奇) & Kenneth Lan…

    C++ 2023年5月29日
    084
  • 从C++到GO

    刚开始接触Go语言,看了两本Go语言的书,从c++开发者的角度来看看go语言的新特性,说下自己感触较深的几点: 并发编程 Go语言层面支持协程,将并发业务逻辑从异步转为同步,大幅提…

    C++ 2023年5月29日
    057
  • C++C#联合调试

    https://blog.csdn.net/BYH371256/article/details/79815097 Original: https://www.cnblogs.com…

    C++ 2023年5月29日
    062
  • C++ 使用静态链接库和动态链接库

    C++ 使用AdbHelper静态链接库 ## 必备文件:静态库AdbHelper.h,AdbHelper.lib以及动态库AdbHelper.dll ##   资源文件使用用法:…

    C++ 2023年5月29日
    055
  • clang-format 对 c++ 进行格式化

    在 VS Code 中安装了 C/C++ 插件后会自动带上格式化工具 clang-format。按 option+shift+f 即可对文件进行 format(格式化)。 在目录下…

    C++ 2023年5月29日
    075
  • C++中 线程函数为静态函数 及 类成员函数作为回调函数

    线程函数为静态函数: 线程控制函数和是不是静态函数没关系,静态函数是在构造中分配的地址空间,只有在析构时才释放也就是全局的东西,不管线程是否运行,静态函数的地址是不变的,并不在线程…

    C++ 2023年5月29日
    065
  • c++ string 和wstring 之间的互相转换函数

    #include <string> std::string ws2s(const std::wstring& ws) { std::string curLoca…

    C++ 2023年5月29日
    057
  • C++中函数调用时的三种参数传递方式详解

    https://blog.csdn.net/zeng_jun_yv/article/details/98868159?utm_medium=distribute.pc_releva…

    C++ 2023年5月29日
    081
  • C++自带string类的常用方法

    #include #include<string> using namespace std; int main() { string str1 = "hell…

    C++ 2023年5月29日
    059
  • Delphi XE8,C++ Builder XE8,RAD Studio XE8 官方 ISO 文件下载,附激活工具

    RAD Studio XE8 v22.0.19027.8951 官方ISO下载(6.72G):http://altd.embarcadero.com/download/radstu…

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