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

大家都在看

  • (筆記) 如何讀取binary file某個byte連續n byte的值? (C/C++) (C)

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

    C++ 2023年5月29日
    069
  • C++11智能指针处理Array对象

    //C++11的//完全可以避免写手动的delete代码,//但是它默认使用delete删除对象,//如果是数组对象,需要指定自定义的删除方法,支持delete[]std::sha…

    C++ 2023年5月29日
    053
  • 聊聊 C++ 中的四种类型转换符

    一:背景 在玩 C 的时候,经常会用 void* 来指向一段内存地址开端,然后再将其强转成尺度更小的 char* 或 int* 来丈量一段内存,参考如下代码: int main()…

    C++ 2023年5月29日
    080
  • C++11新特性学习

    http://www.cprogramming.com/c++11/c++11-lambda-closures.html Original: https://www.cnblogs…

    C++ 2023年5月29日
    063
  • 当C++遇到iOS应用开发—Dict集合

    在Object-c中,字典(KEY/VALUE)使用NSDictionary 和NSMutableDictionary(可变长)。使用语法如下: NSDictionary *dic…

    C++ 2023年5月29日
    081
  • UML——从类图到C++

    简易软件开发流程 实践中,use case and description、class diagram与sequence diagram三者搭配,几乎是UML项目的基本类型,所以在…

    C++ 2023年5月29日
    0101
  • error: Microsoft Visual C++ 14.0 is required问题最佳解决方法

    对于程序员来说,经常pip安装自己所需要的包,大部分的包基本都能安装,但是总会遇到包安装不了的问题,预研学习的动力第一步就被安装包给扼杀了。其中最受困扰的就是这个问题:error:…

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

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

    C++ 2023年5月29日
    073
  • C++多线程库的常用类 std::mutex

    格式:类名 + 头文件 + 用例 + 解释说明 解释说明: std::mutex C++提供的互斥量,用在多线程编程中,来保护共享数据。 C++中通过实例化 std::mutex创…

    C++ 2023年5月29日
    069
  • C++ STL std::copy 详解

    std::copy(start, end, std::back_inserter(container)); 这里,start和end是输入序列(假设有N个元素)的迭代器(itera…

    C++ 2023年5月29日
    086
  • tuple c++

    A tuple is a C++11 construction and it is built heavily on variadic templates. A tuple is …

    C++ 2023年5月29日
    079
  • C++map值排序

    class Solution { public: static bool cmp(pair a, pair b){ return a.second>b.second; } s…

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

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

    C++ 2023年5月29日
    0101
  • 《Accelerated C++》学习笔记(1)——学习资料

    最近找到一本C++的书籍,英文名字《 Accelerated C++: Practical Programming by Example》,作者 Andrew Koenig, Ba…

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

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

    C++ 2023年5月29日
    064
  • The main difference between Java & C++(转载)

    C++ supports pointers whereas Java does not pointers. But when many programmers questioned…

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