右值引用与转移语义(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++11 thread

    官方例子 // thread example #include // std::cout #include // std::thread #include using namesp…

    C++ 2023年5月29日
    064
  • vscode配置c++

    在.vscode里创建三个文件 c_cpp_properties.json, launch.json, settings.json, tasks.json c_cpp_proper…

    C++ 2023年5月29日
    066
  • C++选择文件打开方式的函数

    最近让同事给UE4一个功能,识别出 .ts、.json文件,然后双击这些文件可以直接打开。 默认双击 .json 时,调用 Windows 自带的记事本打开文件,不习惯,想着能否像…

    C++ 2023年5月29日
    058
  • 34.C++-QT信号槽分析

    moc 元对象编译器, 全称是 Meta-Object Compiler,也就是”元对象编译器”。是QT翻译扩展语法到C++语言的工具,目前见扩展了信号与槽…

    C++ 2023年5月29日
    053
  • ProtoBuf3 C++使用篇

    protobuf 是用于结构化数据串行化的灵活、高效、自动化的解决方案。又如 XML,不过它更小、更快、也更简单。你只需要按照你想要的数据存储格式编写一个.proto,然后使用生成…

    C++ 2023年5月29日
    049
  • vscode c++插件与配置

    1 本地运行 c/c++ –代码包 code runner –运行包 –C, C++, Java, JS, PHP, Python, Perl,…

    C++ 2023年5月29日
    080
  • C++菜鸟经验:如何有效地避免各种不期而遇的Bug

    本文展示了笔者在编写 C++程序中遇到的问题和解决方案。文中附有大量有用的代码,这些代码往往都可以不加修改的添加进你自己的函数包中。你可能不能在其他的书上找到这些写法,因为这些都是…

    C++ 2023年5月29日
    039
  • Emacs中使用company + irony实现C++代码补全

    下面是主要配置,一些插件可能需要emacs版本 >= 25.1 对于Irony的话,需要在emacs中手动执行 M-x irony-install-server 来安装好ir…

    C++ 2023年5月29日
    038
  • [C++] const与重载

    下面的两个函数构成重载吗? cpp;gutter:true; void M(int a){} //(1) void M(const int a){} //(2)</p>…

    C++ 2023年5月29日
    081
  • 【面试攻略】C++面试-边锋

    2020-11-26-边锋 1.说说你以前的架构2.C++11特性,好像问到了这个constexpr https://www.jianshu.com/p/5480c4a35d1d3…

    C++ 2023年5月29日
    056
  • c++使用用空格拼接字符串_accumulate用法

    std::accumulate(std::begin(x), std::end(x), string(), [](string &ss, string &s){re…

    C++ 2023年5月29日
    071
  • C++ extern用法总结(转)

    在C语言中,修饰符extern用在变量或者函数的声明前,用来说明”此变量/函数是在别处定义的,要在此处引用”。 (1)extern修饰变量的声明 如果文件a…

    C++ 2023年5月29日
    043
  • C++11 lambda表达式

    C++11引入了lambda表达式,使得程序员可以定义匿名函数,该函数是一次性执行的,既方便了编程,又能防止别人的访问。 Lambda表达式的语法通过下图来介绍: 这里假设我们定义…

    C++ 2023年5月29日
    051
  • C++高性能服务器框架——日志系统

    日志文件系统 对文件系统进行修改时,需要进行很多操作。这些操作可能中途被打断,也就是说,这些操作不是”不可中断”(atomic)的。如果操作被打断,就可能造…

    C++ 2023年5月29日
    063
  • C#与C++之间类型的对应

    Windows Data Type .NET Data Type BOOL, BOOLEAN Boolean or Int32 BSTR String BYTE Byte CHAR…

    C++ 2023年5月29日
    081
  • (筆記) 如何讀取binary file某個byte的值? (C/C++) (C)

    Abstract通常公司為了保護其智慧財產權,會自己定義檔案格式,其header區會定義每個byte各代表某項資訊,所以常常需要直接對binary檔的某byte直接進行讀取。 In…

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