C++之左值、右值、std::forward、std::move总结(二百五十)

2023-10-28 23:45

本文主要是介绍C++之左值、右值、std::forward、std::move总结(二百五十),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解C++之lambda匿名函数、typedef、using等用法

2.左值、右值功能介绍

1.C++左值、右值概念

  • C++中的左值(lvalue)和右值(rvalue)是表达式的属性,用于表示它们在赋值操作中的行为和特性。

  • 左值(lvalue)表示一个可以标识内存位置的表达式,它可以出现在赋值语句的左边或右边。左值可以被引用(可以取得其地址)并且在程序的生命周期中保持稳定。简而言之,左值可以出现在等号左边或右边,并且在其他表达式中可以被引用。

  • 右值(rvalue)表示一个临时的、无法标识内存位置的表达式,它只能出现在赋值语句的右边。右值不能被引用并且在表达式执行完成后可能会被销毁。右值通常是临时生成的中间结果或字面常量。

2.代码实例

  1. 左值示例:
int a = 5;  // 'a'是一个左值,可以在赋值语句的左边或右边使用int b = a;  // 'a'作为右值,它的值被赋给'b'int c = a + b;  // 'a'和'b'都是左值,可以在表达式中进行运算int* ptr = &a;  // 'a'的地址可以被引用
  1. 右值示例:
int result = 2 + 3;  // '2 + 3'是一个右值,表示一个临时的表达式结果int&& temp = 2 + 3;  // '2 + 3'作为右值引用存储在一个右值引用变量中int getValue();  // 函数返回一个右值int value = getValue();  // 函数返回的值是一个右值

3.std::move、std::forward功能介绍

1.std::move、std::forward概念

std::forwardstd::move是C++标准库中提供的两个函数模板,用于实现移动语义和完美转发(perfect forwarding)。它们在C++11引入的右值引用语法的基础上,提供了更灵活和高效的资源管理和函数参数传递方式。

    1. std::move函数:
    • std::move用于将一个左值(lvalue)转换为右值引用(rvalue reference),从而能够实现移动语义。
    • 它是通过使用静态转换static_cast来实现的,并且没有运行时开销。
    • std::move的主要作用是为了在移动语义的情况下,将资源的所有权从一个对象转移到另一个对象,避免了不必要的复制操作,提高了性能。
  • 2.std::forward`函数:

    • std::forward用于实现完美转发,将函数参数以原有的左值或右值引用方式传递,保持类型不变。
    • 它用于解决函数模板中传递参数的类型保持一致性的问题,能够将右值引用转发为右值引用,将左值引用转发为左值引用。
    • std::forward通过使用模板推导和引用折叠规则来实现。

2.代码实例

v1.0 std::move实例
#include <iostream>
#include <vector>
#include <string>using namespace std;int main(){//v1.0 std::move()用法.string buf1 = "123";//string&& Rval1 = buf1;//failed:将左值赋值给右值引用.string&& Rval3 = std::move(buf1);//std::move(): 将左值转为右值,赋值给右引用.cout << buf1 << endl; return 0;
}
v2.0 std::move实例
#include <iostream>
using namespace std;void test(int& x) {printf("xxx------>line = %d, 左值 = %d\n",__LINE__,x);
}void test(int&& x) {printf("xxx------>line = %d, 右值 = %d\n",__LINE__,x);
}template<typename T>
void foo(T&& arg) {test(std::forward<T>(arg));
}void test_1(int x){printf("xxx------>line = %d, 右值 = %d\n",__LINE__,x);
}void test_2(int& x){printf("xxx------>line = %d, 右值 = %d\n",__LINE__,x);
}int main() {//v1.0int x = 42;test_2(x);//OK:因为test_2接收的是左值,因为x为左值.//test_2(42);//报错:接收右值,因为test_2()只接收左值.//v2.0:不是设置参数的类型左值(int &)或右值(int &&),则可以接收左值或右值.int y = x + 1;test_1(x+1);//接收右值:x+1test_1(y);//接收左值:y//v3.0:通过forward完美左值或右值转换foo<>(x); //接收左值: xfoo<int>(42); //接收右值: 42return 0;
}

这篇关于C++之左值、右值、std::forward、std::move总结(二百五十)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/296783

相关文章

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Java向kettle8.0传递参数的方式总结

《Java向kettle8.0传递参数的方式总结》介绍了如何在Kettle中传递参数到转换和作业中,包括设置全局properties、使用TransMeta和JobMeta的parameterValu... 目录1.传递参数到转换中2.传递参数到作业中总结1.传递参数到转换中1.1. 通过设置Trans的

C# Task Cancellation使用总结

《C#TaskCancellation使用总结》本文主要介绍了在使用CancellationTokenSource取消任务时的行为,以及如何使用Task的ContinueWith方法来处理任务的延... 目录C# Task Cancellation总结1、调用cancellationTokenSource.

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数