iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++右值引用的示例分析
  • 399
分享到

C++右值引用的示例分析

2023-06-15 09:06:57 399人浏览 独家记忆
摘要

这篇文章主要介绍了c++右值引用的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。概述在C++中,常量、变量或表达式一定是左值(lvalue)或右值(rvalue)。左

这篇文章主要介绍了c++右值引用的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

概述

在C++中,常量、变量或表达式一定是左值(lvalue)或右值(rvalue)。

左值:非临时的(具名的,可在多条语句中使用,可以被取地址)。可以出现在等号的左边或右边。可分为非常量左值和常量左值。

C++右值引用的示例分析

右值:临时的(不具名的,只在当前语句中有效,不能取地址)。只能出现在等号的右边。可分为非常量右值和常量右值。

C++右值引用的示例分析

左值引用:对左值的引用就是左值引用。可分为非常量左值引用和常量左值引用。

C++右值引用的示例分析

注:常量左值引用是“万能”的引用类型,可以绑定到所有类型的值,包括非常量左值、常量左值、非常量右值和常量右值。

右值引用(Rvalue References):对右值的引用就是右值引用。可分为非常量右值引用和常量右值引用。

C++右值引用的示例分析

为临时对象的右值,它的生命周期很短暂,一般在执行完当前这条表达式之后,就释放了。

通过将其赋值给右值引用,可以在不进行昂贵的拷贝操作的情况下被“续命”,让其生命周期与右值引用类型变量的生命周期一样长。

右值引用的两个基本特性:移动语义(Move Semantics)和完美转发(Perfect Forwarding)

移动语义(Move Semantics)

可将资源从一个对象转移到另一个对象;主要解决减少不必要的临时对象的创建、拷贝与销毁。

移动构造函数MyClass(Type&& a):当构造函数参数是一个右值时,优先使用移动构造函数而不是拷贝构造函数MyClass(const Type& a)。

移动赋值运算符Type& operator = (Type&& a):当赋值的是一个右值时,优先使用移动赋值而不是拷贝赋值运算符Type& operator = (const Type& a)。

#include <iOStream>#include <string>#include <utility>struct MyClass{    std::string s;    MyClass(const char* sz) : s(sz)     {        std::cout << "MyClass sz:" << sz << std::endl;    }    MyClass(const MyClass& o) : s(o.s)     {         std::cout << "copy construct!\n";     }    MyClass(MyClass&& o) noexcept : s(std::move(o.s))     {        std::cout << "move construct!\n";    }    MyClass& operator=(const MyClass& other) { // copy assign        std::cout << "copy assign!\n";        s = other.s;        return *this;    }    MyClass& operator=(MyClass&& other) noexcept { // move assign        std::cout << "move assign!\n";        s = std::move(other.s);        return *this;    }    static MyClass GetMyClassGo(const char* sz)    {        MyClass o(sz); // 注意:可能会被NRVO优化掉        return o;    }};void func0(MyClass o){    std::cout << o.s.c_str() << std::endl;}void func1(MyClass& o){    std::cout << o.s.c_str() << std::endl;}void func2(const MyClass& o){    std::cout << o.s.c_str() << std::endl;}void func3(MyClass&& o){    std::cout << o.s.c_str() << std::endl;}int main(int arg, char* argv[]){    MyClass a1("how");    MyClass a2("are");    a2 = a1; // copy assign  注:a1是一个左值    a2 = MyClass("you"); // move assign  注:MyClass("you")是一个右值    MyClass a3(a1); // copy construct  注:a1是一个左值    MyClass&& a4 = MyClass::GetMyClassGo("go"); // move construct  注:发生在MyClass::GetMyClassGo()内部    MyClass a5 = MyClass::GetMyClassGo("china"); // move construct两次  注:一次发生在MyClass::GetMyClassGo()内部;另一次发生在将返回值赋值给a5        MyClass a6("let");    MyClass a7("it");    MyClass a8("go");    MyClass a9("!");    func0(a6);  // copy construct    func1(a7);    func2(a8);    //func3(a9); // 编译error: 不能把一个左值赋值给右值    func0(MyClass::GetMyClassGo("god")); // move construct两次  注:一次发生在MyClass::GetMyClassGo()内部;另一次发生在将返回值赋值给foo0参数时    //func1(MyClass::GetMyClassGo("is")); // 编译error: 不能把一个右值赋值给左值    func2(MyClass::GetMyClassGo("girl")); // move construct  注:发生在MyClass::GetMyClassGo()内部    func3(MyClass::GetMyClassGo("!"));  // move construct  注:发生在MyClass::GetMyClassGo()内部    return 0;}

注:测试以上代码一定要关闭C++编译器优化技术 -- RVO、NRVO和复制省略

使用std::move来实现移动语义

将一个左值或右值强制转化为右值引用。 注:UE4中对应为MoveTemp模板函数

std::move(en chs)并不会移动任何东西,只是将对象的状态或者所有权从一个对象转移到另一个对象。注:只是转移,没有内存的搬迁或者内存拷贝。

① 基本类型(如:int、double等)被std::move移动后,其数值不会发生变化

② 复合类型被std::move移动后,处于一个未定义,但有效的状态(大部分成员函数仍有意义)例如:标准库中的容器类对象被移动后,会变成空容器

完美转发(Perfect Forwarding)

针对模板函数,使用全能引用将一组参数原封不动的传递给另一个函数。

原封不动指:左值、右值、是否为const均不变。带来如下3方面好处:

① 保证左值、右值的属性

② 避免不必要的拷贝操作

③避免模版函数需要为左值、右值、是否为const的参数来实现不同的重载

全能引用(universal references、转发引用)是一种特殊的模板引用类型,采用右值引用的语法形式(但它并不是右值引用)。如:template <class T> void func(T&& t) {}

T&& t在发生自动类型推断的时候,它是未定的引用类型(universal references),T取决于传入的参数t是右值还是左值。右值经过T&&变为右值引用,而左值经过T&&变为左值引用。

std::move就是使用全能引用实现的。其定义如下:

template <typename T>typename remove_reference<T>::type&& move(T&& t){    return static_cast<typename remove_reference<T>::type &&>(t);}//原始的,最通用的版本template <typename T> struct remove_reference{    typedef T type;  //定义T的类型别名为type}; //部分版本特例化,将用于左值引用和右值引用template <class T> struct remove_reference<T&> //左值引用{ typedef T type; } template <class T> struct remove_reference<T&&> //右值引用{ typedef T type; }

① 当t为左值时,展开为:U&& move(U& t)  注:右值引用类型变量也是左值

② 当t为右值时,展开为:U&& move(U&& t)

最后,通过static_cast<>进行强制类型转换返回右值引用。注:static_cast之所以能使用类型转换,是通过remove_refrence::type模板移除T&&,T&的引用,获取具体类型T(模板偏特化)。

引用折叠

规律:含左值引用就是左值引用,否则就是右值引用

C++右值引用的示例分析

使用std::forward实现参数的完美转发。其定义如下(en chs):

template <typename T>T&& forward(remove_reference_t<T>& arg) // forward an lvalue as either an lvalue or an rvalue{     return static_cast<T&&>(arg);}template <typename T>T&& forward(remove_reference_t<T>&& arg) // forward an rvalue as an rvalue{     static_assert(!is_lvalue_reference_v<T>, "bad forward call");    return static_cast<T&&>(arg);}

最后,通过static_cast<>进行引用折叠,并强制类型转换后,实现原封不动转发参数。 注:UE4中对应为Forward模板函数

void bar(int& a, int&& b){    int c = a + b;}void func(int a, int&& b){    int c = a + b;}template <typename A, typename B>void foo(A&& a, B&& b) { // a, b为左值引用或右值引用    bar(std::forward<A>(a), std::forward<B>(b)); // 在std::forward转发前后,参数a,b的类型完全不变}int main(int arg, char* argv[]){    int a = 10;    foo(a, 20); // 展开为void foo(int& a, int&& b),经过std::forward完美转发后,会调用到void bar(int& a, int&& b)函数    func(std::forward<int>(a), std::forward<int&&>(30)); // 经过std::forward完美转发后,会调用到void func(int a, int&& b)函数    return 0;}

感谢你能够认真阅读完这篇文章,希望小编分享的“C++右值引用的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网其他教程频道,更多相关知识等着你来学习!

--结束END--

本文标题: C++右值引用的示例分析

本文链接: https://www.lsjlt.com/news/279349.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++右值引用的示例分析
    这篇文章主要介绍了C++右值引用的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。概述在C++中,常量、变量或表达式一定是左值(lvalue)或右值(rvalue)。左...
    99+
    2023-06-15
  • C++11语法之右值引用的示例讲解
    目录一、{}的扩展initializer_list的讲解:二、C++11一些小的更新decltypenullptr范围for新容器三、右值引用右值真正的用法完美转发默认成员函数总结一...
    99+
    2024-04-02
  • C++中引用的示例分析
    这篇文章将为大家详细讲解有关C++中引用的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。背景在c/c++中,访问一个变量只能通过两种方式被访问,传递,或者查询。这两种方式是:通过值访问/传递变量通...
    99+
    2023-06-15
  • Python与C++引用的示例分析
    本篇文章给大家分享的是有关Python与C++引用的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在用Python写建二叉树的代码的时候遇到了这个问题,原因就是把Pyt...
    99+
    2023-06-02
  • C++11右值引用和移动语义的实例解析
    目录基本概念左值 vs 右值左值引用 vs 右值引用右值引用使用场景和意义左值引用的使用场景左值引用的短板右值引用和移动语义右值引用引用左值右值引用的其他使用场景完美转发万能引用完美...
    99+
    2024-04-02
  • C++精要分析右值引用与完美转发的应用
    目录区分左值与右值右值引用移动语义完美转发结语区分左值与右值 在C++面试的时候,有一个看起来似乎挺简单的问题,却总可以挖出坑来,就是问:“如何区分左值与右值?&rdqu...
    99+
    2024-04-02
  • C++中指针引用的示例分析
    这篇文章主要介绍C++中指针引用的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!指针和引用形式上很好区别,但是他们似乎有相同的功能,都能够直接引用对象,对其进行直接的操作。首先,引用不可以为空,但指针可以为空...
    99+
    2023-06-25
  • C++右值如何引用
    本篇内容介绍了“C++右值如何引用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.左值和右值在我们之前的文章当中,介绍的都是左值引用。C+...
    99+
    2023-06-22
  • 详解C++右值引用
    目录概述移动语义(Move Semantics)完美转发(Perfect Forwarding)概述 在C++中,常量、变量或表达式一定是左值(lvalue)或右值(rvalue)。...
    99+
    2024-04-02
  • JavaScript对象引用与赋值的示例分析
    小编给大家分享一下JavaScript对象引用与赋值的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!具体如下:<script type="text/jav...
    99+
    2024-04-02
  • C++中指针,引用和STL的示例分析
    这篇文章主要介绍C++中指针,引用和STL的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!对象的定义:对象是指一块能存储数据并具有某种类型的内存空间一个对象a,它有值和地址;运行程序时,计算机会为该对象分配存...
    99+
    2023-06-29
  • C++的shared_ptr与右值如何引用
    今天小编给大家分享一下C++的shared_ptr与右值如何引用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. 介绍在 ...
    99+
    2023-06-19
  • Java中值传递和引用传递的示例分析
    小编给大家分享一下Java中值传递和引用传递的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、前言最近在看Java核心卷一,也就是这本书:在这本书里面也...
    99+
    2023-06-15
  • Java中引用类型和值类型的示例分析
    这篇文章给大家分享的是有关Java中引用类型和值类型的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。值类型传值,引用类型传引用Demo:public class ReferDemo {   &n...
    99+
    2023-06-03
  • 引用和Threadlocal的示例分析
    引用和Threadlocal的示例分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1 背景某一天在某一个群里面的某个群友突然提出了一个问题:"threadlocal...
    99+
    2023-06-04
  • C++11万能引用和右值引用的方法
    这篇文章主要介绍了C++11万能引用和右值引用的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++11万能引用和右值引用的方法文章都会有所收获,下面我们一起来看看吧。正文实际上,type&&...
    99+
    2023-06-29
  • HTML中引用的示例分析
    小编给大家分享一下HTML中引用的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! 引用(Quotation) 这是摘...
    99+
    2024-04-02
  • C语言中返回值的示例分析
    这篇文章给大家分享的是有关C语言中返回值的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 函数返回值定义的结构在<cstdlib>,其中有两个成员。为 di...
    99+
    2024-04-02
  • 一篇文章弄懂C++左值引用和右值引用
    目录1. 左值和右值 2. 左值引用 3. 右值引用 3.1 出现 3.2 概念 3.3 应用 3.3.1 右值引用绑定到左值上 3.3.2 std::move()本质 3.3.3 ...
    99+
    2024-04-02
  • C语言中什么是左值引用与右值引用
    这篇文章主要介绍“C语言中什么是左值引用与右值引用”,在日常操作中,相信很多人在C语言中什么是左值引用与右值引用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言中什么是左值引用与右值引用”的疑惑有所帮助!...
    99+
    2023-06-16
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作