C++ 学习系列 1 -- 左值、右值与万能引用

news2025/5/17 8:51:12

1. 何为左值?何为右值?

简单的说,左值可以放在等号的左边,右值可以放在等号的右边。

左值可以取地址,右值不能取地址。

1.1 左值举例:

  • 变量、函数或数据成员
  • 返回左值引用的表达式 如 ++x、x = 1、cout << ' '  int x = 0

1.2 右值举例:

  • 返回非引用类型的表达式
    如 x++、x + 1
  • 除字符串字面量之外的字面量如 42、true
将亡值(xvalue)
  • 隐式或显式调用函数的结果,该函数的返回类型是对所返回对象类型的右值引用
#include<string>
#include<iostream>
using namespace std;
void print(string& str)
{
    cout << "left val: " <<str << endl << endl;
}

void print(string&& str)
{
    cout << "right val: " << str <<endl << endl;
}



void print(int&& i)
{
    cout << "right val: " <<i << endl << endl;
}

void print(int& i)
{
    cout << "left val: " <<i << endl << endl;
}

int getVal(){
    return 666;
}

int main(int argc, char *argv[])
{
    string str1 = "hello 1";
    print(str1);
    print("hello 2");
    print(move(str1));

    int ab = 88;
    print(ab);
    print(++ab);
    print(ab++);

    print(getVal());

    //string& aa = "abc"; // 编译不过,左值引用不可以赋右值
    const string& bb = "abc"; // 常量左值引用可以赋右值


    return 0;
}

输出:

 1.3 左值引用与右值引用

 

规则简化如下:

左值引用   {左值}  
右值引用   {右值}
常左值引用  {右值}
string f()
{
   return "bbb";
}

int main() 
{

  string &s1 = "asd";  // error
  const string &s2 = "asd";  // ok
  const string& s3 = f();  // ok
  
  string&& a2 = "defg"; // ok
  string&& a3 = f(); // ok
  
  return 0;
}

  1.4 引入右值引用意义

  可以延长右值的生命周期,右值的生命周期可以与右值引用变量相同

2. 完美转发

2.1  转发引用

在 T 是模板参数时,T&& 的作用主要是保持值类别进行转发,它有个名字就叫“转发引用”(forwarding reference)。因为既可以是左值引用,也可以是右值引用,它也曾经被叫做“万能引用”(universal reference)。

#include<string>
#include<iostream>
using namespace std;
void print(const string& str)
{
    cout << "left val: " <<str << endl << endl;
}

void print(string&& str)
{
    cout << "right val: " << str <<endl << endl;
}

string ff()
{
    return "fff";
}

template<typename T>
void f(T&& param)
{
    print(forward<T>(param));
}

int main(int argc, char *argv[])
{
    string str1 = "hello 1";
    const string& bb = "abc";
    const string& bb2 = ff();


    f(str1); // left value
    f(bb); // left value
    f(bb2); // left value
    f("abcd"); // rightvalue
    f(ff()); // right value

    return 0;
}

输出:

 2.2  完美转发 std::forward

 2.1.1 源码解析
  • 转发左值
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type& __t) noexcept
{ return static_cast<_Tp&&>(__t); }

先通过 remove_reference 获得类型type,定义_t为左值引用的左值变量,通过 static_cast 进行强制转换

  • 转发右值
template<typename _Tp>
constexpr _Tp&&
forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
{
  static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
        " substituting _Tp is an lvalue reference type");
  return static_cast<_Tp&&>(__t);
}
   不同于转发左值,_t为右值引用的左值变量,除此之外中间加了一个断言,表示当不是左值的时候,也就是右值,才进行static_cast转换。
2.1.2  remove_reference 解析
template<typename _Tp>
struct remove_reference
{ typedef _Tp   type; };

// 特化版本
template<typename _Tp>
struct remove_reference<_Tp&>
{ typedef _Tp   type; };

template<typename _Tp>
struct remove_reference<_Tp&&>
{ typedef _Tp   type; };

remove_reference的作用是去除T中的引用部分,只获取其中的类型部分。无论T是左值还是右值,最后只获取它的类型部分。

现代C++之万能引用、完美转发、引用折叠 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/857160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Keystone Automotive EDI 需求分析

Keystone Automotive 是一家知名的汽车零部件销售卖场&#xff0c;自创立以来&#xff0c;在汽车行业取得了卓越的成就。作为一家专业的汽车零部件供应商&#xff0c;Keystone Automotive 致力于为客户提供优质的产品和卓越的服务。公司的经营范围涵盖广泛&#xff0c;涉及多个…

ubuntu python虚拟环境venv搭配systemd服务实战

文章目录 参考文章目录结构步骤安装venv查看python版本创建虚拟环境激活虚拟环境运行我们程序看缺少哪些依赖库&#xff0c;依次安装它们接下来我们配置python程序启动脚本&#xff0c;脚本中启动python程序前需先激活虚拟环境配置.service文件然后执行部署脚本&#xff0c;成功…

unity vscode 代码关联 跳转 BUG

一早打开电脑发现代码关联失效了&#xff0c;目测可能跟昨天一些插件更新有关 结论 就这货&#xff0c;开了就没法提示代码关联&#xff0c;估计预览版全是BUG。 另一个坑 同期有个unity插件也是预览版&#xff0c;“非常好使”&#xff0c;当场去世。评论点开有好几个人说用…

cadence virtuoso worning

cadence virtuoso 添加工艺库报错如下&#xff1a; Warning: ddUpdateLibList: It appears that you are trying to run an OA executable on CDB data. Library smic13mmrf_1233 contains file /home/IC/Tech/PDK_13mmrf_1P6M_30k/smic13mmrf_1233/prop.xx which is CDB data.…

Taro React组件使用(11) —— RuiNoticebar 公告栏

1. 需求分析 用于循环播放展示一组消息通知&#xff1b;通知消息渲染完成&#xff0c;获取消息的长度和盒子的长度&#xff1b;使用【taro react】---- 获取元素的位置和宽高等信息异步获取内容和盒子的宽高信息&#xff1b;通过 CSS3 的 animation 实现内容的移动&#xff1b…

Flume拦截器

实现 Interceptor接口 方法1 是初始化: 方法2和3重载 拦截: 方法3 是关闭: 但是flume是通过内部类创建对象的

一、Kubernetes介绍与集群架构

Kubernetes介绍与集群架构 一、认识容器编排工具 docker machine 主要用于准备docker host现已弃用建议使用docker desktop docker compose Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。使用 Compose&#xff0c;您可以使用 YAML 文件来配置应用程序的服务。…

c语言--浮点数(float)与0值比较

我们定义一个float类型的数据a&#xff0c;赋值为123456789并输出&#xff1a; int main() {float a;a 123456789;printf("%f\n",a);return 0; }输出结果为&#xff1a; 由此可以看出&#xff0c;程序输出的结果并不是其被赋予的值。即说明了浮点数存在一定的误差。…

MD-MTSP:星雀优化算法NOA求解多仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)

一、星雀优化算法NOA 星雀优化算法(Nutcracker optimizer algorithm,NOA)由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模拟星雀的两种行为&#xff0c;即&#xff1a;在夏秋季节收集并储存食物&#xff0c;在春冬季节搜索食物的存储位置。星雀优化算法(Nutcrack…

Optional 使用方法详解

Optional的作用是什么&#xff1f;他都有哪些方法&#xff1f;阿里规范点名说尽量用Optional来避免空指针&#xff0c;那么什么场景用Optional&#xff1f;本篇文章围绕这三点来进行讲解。 一、Optional类的来源 到目前为止&#xff0c;臭名昭著的空指针异常是导致Java应用程…

Go For Web:踏入Web大门的第一步——Web 的工作方式

Web 的工作方式 了解当你访问一个网页时&#xff0c;背后是如何运作的&#xff0c;发生了一些什么&#xff1f; 其实当你输入网址&#xff08;URL&#xff09;并按下回车之后&#xff0c;你的浏览器相当于扮演了 客户端 的角色&#xff0c;首先你的浏览器会去请求 DNS 服务器进…

uniapp软键盘谈起遮住输入框和头部被顶起的问题解决

推荐&#xff1a; pages.json中配置如下可解决头部被顶起和表单被遮住的问题。 { "path": "pages/debug/protocol/tagWord", "style": { "app-plus": { "soft…

外呼系统是什么?有什么功能?AI智能系统人工系统

很多企业往往会选择通过使用外呼系统来解决封卡问题。与传统人工拨打相比&#xff0c;外呼系统一方面可以协助销售进行高效外呼&#xff0c;同时还能保障线路稳定不封号&#xff0c;与系统的接入也可以保证客户信息的跟进&#xff0c;助力销售持续性跟进。但是看到这里也不要误…

php通过各种函数判断0和空php实例

php通过各种函数判断0和空php实例 本文给大家介绍php同各种函数判断0和空的方法&#xff0c;在文章给大家补充介绍了php 语法里0不等于null为空的解决办法 补充&#xff1a;下面给大家介绍下php 语法里0不等于null为空的解决办法 今天遇到这样一个问题是这样的: php 语句里,我…

Allure2测试报告详解

目录&#xff1a; allure2安装allure2运行方式allure2报告生成allure2报告中添加用例标题allure2报告中添加用例步骤allure2报告中添加用例链接allure2报告中添加用例分类allure2报告中添加用例描述allure2报告中添加用例优先级allure2报告中添加用例支持tags标签allure2报告中…

冠达管理:A股继续缩量整理 创业板指数走势相对偏强

周三&#xff0c;A股低开后震动调整&#xff0c;三大指数均小幅跌落&#xff0c;创业板指相对偏强。到收盘&#xff0c;上证综指跌0.49%&#xff0c;报3244.49点&#xff1b;深证成指跌0.53%&#xff0c;报11039.45点&#xff1b;创业板指跌0.01%&#xff0c;报2228.73点。 资金…

用于3D MRI和CT扫描的深度学习模型总结

医学成像数据与其他我们日常图像的最大区别之一是它们很多都是3D的&#xff0c;比如在处理DICOM系列数据时尤其如此。DICOM图像由很多的2D切片组成了一个扫描或身体的特定部分。 那么如何为这类数据构建深度学习解决方案呢?本文中将介绍6种神经网络架构&#xff0c;可以使用它…

Window版 Redis6.0.6安装

一、准备工作 下载Redis6.0.6版本&#xff08;redis官网地址&#xff1a;http://www.redis.cn/download.html&#xff09; 下载MSYS2&#xff08;清华的源&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/msys2/distrib/x86_64/&#xff09; 安装板exe结尾的文件&#xf…

chapter14:springboot与安全

Spring Boot与安全视频 Spring Security, shiro等安全框架。主要功能是”认证“和”授权“&#xff0c;或者说是访问控制。 认证&#xff08;Authentication&#xff09;是建立在一个声明主体的过程&#xff08;一个主体一般指用户&#xff0c;设备或一些可以在你的应用程序中…

【ARM64 ATF 系列 3 -- ARM64 warm reset 与 cold reset】

文章目录 ARM64 Reset1.1.1 reset 运行级别1.1.2 warm reset 寄存器1.1.3 PSCI Suspend/Resume ARM64 Reset ARMv8-A支持两种复位&#xff0c;冷复位和热复位。两者主要区别是冷复位会将debug 功能模块也一同复位&#xff0c;热复位在默认情况则不会复位 debug 功 能模块。 处理…