<五>move移动语义和forward类型转发

move : 移动语义,得到右值类型
forward:类型转发,能够识别左值和右值类型

只有两种形式的引用,左值引用和右值引用,万能引用不是一种引用类型,它存在于模板的引用折叠情况,但是能够接受左值和右值
区分左值和右值得一个简单方式就是能不能取地址
一个右值一旦有名字那么就变成了左值

#include <iostream>
using namespace std;

void process(int & i) {
	std::cout << i << " lvalue" << std::endl;
}

void process(int && i) {
	std::cout << i << " r value" << std::endl;
}

template<typename T>
void test(T && v) { //这里的&& 表示万能引用,既能接受左值也能接受右值
	process(v);
}

int main() {

	int i = 100;
	test(i);
	test(200);

	system("pause");
	return 0;
}

<五>move移动语义和forward类型转发

上面的运行结果 我们发现 test(i); 和 test(200); 最后都调用了 void process(int & i) 左值形参,
test(T && v) 接受test(i)的时候,是用左值去接, 接受test(200)的时候,使用右值去接,
其中有一点右值本身是一个左值类型(如何理解?右值本身是有地址有名称的,所以他本身就可以取地址了,他是一个左值)
所以函数形参一定是个左值,他有名字,有空间了,变成了具名对象,200传过去后变成了一个左值.

200 传入 test后就变成了一个左值了,进入了test 函数后没有保留好原始信息,所以 process(v); 就都调用了void process(int & i) 左值形参,
这个我叫做 不完美转发

但是我希望 在test 函数内任然能够保留原始信息,原始的是左值继续保留左值,原始是右值就继续保留右值, 如何实现呢? 完美转发

引用折叠技术

形参 是 T && v ,在模板函数形参,两个引用 在一起会引发引用折叠, 有一个左值引用 最后是=》左值, 两个都是右值 最后是=>右值

即 test(i) + void test(T && v) => T & && i => 左值
即 test(200) + void test(T && v) => T && && 200 => 右值

所以将 函数形参写成 &&

//模板实例化过程中出现这种情况就会发生引用折叠,如果任一尹永伟左值引用,那么结果就是左值引用,
//如果两个都是右值引用,那么结果为右值引用
template<typename T>
void test2(T && v) {	
	std::cout  <<"is int &  " <<  std::is_same_v<T, int &> << std::endl;
	std::cout << "is int    " <<  std::is_same_v<T, int > << std::endl;
}

int main() {

	int i = 100;
	test2(i);
	test2(200);

	system("pause");
	return 0;
}

<五>move移动语义和forward类型转发

template<typename T>
void test2(T && v) {	
	std::cout  <<"is int &  "<< std::is_same_v<T, int &> << std::endl;
	std::cout << "is int    " << std::is_same_v<T, int > << std::endl;
}

int main() {

	int i = 100;
	test2(i);
	test2(200);

	system("pause");
	return 0;
}

test2(i) 调用模板会实例化出如下模板
void test2(int & && v) {	
	std::cout  <<"is int &  "<< std::is_same_v<T, int &> << std::endl;
	std::cout << "is int    " << std::is_same_v<T, int > << std::endl;
}

test2(200) 调用模板会实例化出如下模板
void test2(int && v) {	
	std::cout  <<"is int &  " << std::is_same_v<T, int &> << std::endl;
	std::cout << "is int    " << std::is_same_v<T, int > << std::endl;
}

上面两个实例化出来的模板,形参根据引用折叠技术 
void test2(int & && v) =》void test2(int & v)
void test2(int &&   v) =》void test2(int && v)


即 如果 test2(i)  那么模板中的 T  就是  int &
如果 test2(200 )  那么模板中的 T  就是  int


所以 下面的代码 
template<typename T>
void test(T && v) { //这里的&& 表示万能引用,既能接受左值也能接受右值
	process(v);
}

我们这里这么改一下
template<typename T>
void test(T && v) { //这里的&& 表示万能引用,既能接受左值也能接受右值      
	 
         process(static_cast<T&&>(v));
        // test(i)  => process( static_cast<int & &&>(v)); =>  process( static_cast<int & >(v));
        // test(200)=> process( static_cast<int &&>(v));   =>  process( static_cast<int && >(v));
}


原文链接:https://www.cnblogs.com/erichome/p/16942125.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:<五>move移动语义和forward类型转发 - Python技术站

(0)
上一篇 2023年5月3日
下一篇 2023年5月5日

相关文章

  • Qt源码阅读(四) 事件循环

    事件系统 文章为本人理解,如有理解不到位之处,烦请各位指正。 @ 目录 事件系统 什么是事件循环? 事件是如何产生的? sendEvent postEvent 事件是如何处理的? 事件循环是怎么遍历的? 事件过滤器 event 夹带私货时间 Qt的事件循环,应该是所有Qter都避不开的一个点,所以,这篇博客,咱们来了解源码中一些关于Qt中事件循环的部分。先抛…

    C++ 2023年4月18日
    00
  • linux开发之gdb记录

    简述 GDB, the GNU Project debugger, allows you to see what is going on ‘inside’ another program while it executes — or what another program was doing at the moment it crashed.GDB, G…

    C++ 2023年4月17日
    00
  • 第三部分:Spdlog 日志库的实现原理

    Spdlog 是一个快速、异步的 C++ 日志库,被广泛应用于 C++ 项目中。在这篇文章中,我们将探讨 Spdlog 日志库的实现原理。 Spdlog 的结构 Spdlog 由五个主要组件构成:Loggers、Sinks、Formatters、Async Logger 和 Registry。每个组件都扮演着不同的角色,共同协作记录并输出日志消息。 Logg…

    C++ 2023年4月18日
    00
  • 记一次 腾讯会议 的意外崩溃分析

    一:背景 1. 讲故事 前段时间在用 腾讯会议 直播的时候,居然意外崩溃了,还好不是在训练营上课,不然又得重录了,崩完之后发现 腾讯会议 的 bugreport 组件会自动生成一个 minidump,截图如下: 作为一个.NET高级调试的技术博主,非 .NET 的程序也得要研究研究哈???,有了这个好奇心,也有了这个 dump,接下来用 windbg 看一看…

    C++ 2023年4月22日
    00
  • 【Visual Leak Detector】源码下载

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 源码的下载。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 下载途径 2. 不同下载途径的源文件差异 1. 下载途径 以 v2.5.1 版本为例,可以到 Github-KindDragon-vld 页面下载 master 的 zip 源码包,如下所示: 也可以到 …

    C++ 2023年4月22日
    00
  • 【Visual Leak Detector】配置项 StartDisabled

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 StartDisabled 的使用方法。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 配置文件使用说明 2. 设置是否禁用自动初始化 2.1 测试代码 2.2 StartDisabled = no 时的输出 2.3 StartDisabled …

    C++ 2023年4月18日
    00
  • P6818 [PA2013]Działka 题解

    P6818 [PA2013]Działka 前言 我太菜了。。。。 对着 jiangly 大佬的题解研究了一下午研究了一下午才搞出来(泪目。 作为一个蒟蒻,我就详细的讲一下我对与本题的理解。 题意 本题的的题意描述的还是比较明了。 在二维坐标系中,输入 \(n\) 个点 \(m\) 次询问, 每次询问,给出一个矩阵, 求出矩阵内极大凸包的面积。 题解 1.如…

    C++ 2023年4月30日
    00
  • STL 容器 002 (vector 详解)

    为什么 各方面表现都比较中等, 适用范围广 尾插很快, 查找也比较快 是什么 动态数组 特点: 动态数组, 三个指针控制 两倍增长 扩充的方法: 不能原地扩充, 因为后面可能会有其他的东西, 必须在 其他地方开辟一块更大的内存 提供[] 所有的有连续空间的容器都有[] iterator是class类型的 怎么样 制造 两倍增长 //push_back() 检…

    C++ 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部