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

这篇具有很好参考价值的文章主要介绍了<五>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类型转发文章来源地址https://www.toymoban.com/news/detail-433173.html

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));
}


到了这里,关于<五>move移动语义和forward类型转发的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c++右值引用、移动语义、完美转发

    左值:一般指的是在内存中有对应的存储单元的值,最常见的就是程序中创建的变量 右值:和左值相反,一般指的是没有对应存储单元的值(寄存器中的立即数,中间结果等),例如一个常量,或者表达式计算的临时变量 左值引用:C++中采用 对变量进行引用,这种常规的引

    2024年02月05日
    浏览(54)
  • 【重学C++】05 | 说透右值引用、移动语义、完美转发(下)

    【重学C++】05 | 说透右值引用、移动语义、完美转发(下) 大家好,我是只讲技术干货的会玩code,今天是【重学C++】的第五讲,在第四讲《【重学C++】04 | 说透右值引用、移动语义、完美转发(上)》中,我们解释了右值和右值引用的相关概念,并介绍了C++的移动语义以及如

    2024年02月06日
    浏览(40)
  • 【重学C++】04 | 说透C++右值引用、移动语义、完美转发(上)

    【重学C++】04 | 说透C++右值引用、移动语义、完美转发(上) 大家好,我是只讲技术干货的会玩code,今天是【重学C++】的第四讲,在前面《03 | 手撸C++智能指针实战教程》中,我们或多或少接触了右值引用和移动的一些用法。 右值引用是 C++11 标准中一个很重要的特性。第一

    2024年02月06日
    浏览(45)
  • Rust中的智能指针:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak<T>

    智能指针(smart pointers)是一类数据结构,是拥有数据所有权和额外功能的指针。是指针的进一步发展 指针(pointer)是一个包含内存地址的变量的通用概念。这个地址引用,或 ” 指向”(points at)一些其 他数据 。引用以 符号为标志并借用了他们所 指向的值。除了引用数据

    2023年04月20日
    浏览(59)
  • C++ 中 <iterator> <functional> <numeric> 库好用的函数

    简述:迭代器省代码用的。 std::advance 记忆方法:advance-前进。 形如: advance(it, step) ,表示 it 迭代器自增 step 步。 实现类似于: 或 std::next std::prev 记忆方法:自己问英语老师。 形如 next(it, n) 及 prev(it, n) ,默认 n = 1 ,表示迭代器前移、后移 n 位。 为 std::advance 的变体,区

    2024年02月05日
    浏览(67)
  • C++学习笔记八:极限和数学运算<limits><cmath>

    1) limits库: 1.1 源文档: https://en.cppreference.com/w/cpp/types/numeric_limits #include limits   1.2 库函数: 函数解释: 对于一个浮点数,lowest表示最小的可表示的负数,min表示最小的可表示的接近0的数,max表示最大的可表示的正数 对于一个有符号整数,min表示可以表示的最小的负数,

    2024年02月05日
    浏览(40)
  • 详解dedecms后台编辑器将回车<br>改为<p>的方法

    DEDECMS编辑器默认回车[确认键]是返回 这样的。 有时候我们需要返回 这样的,今天我们就讲讲后台编辑器将回车将 改为 的有效教程吧。 方法也很简单,首先我们找到dedecms后来台编辑器的配置文件。 所在路径为:/include/ckeditor/config.js 我们打开它,里面有两个字: 替换为 这

    2024年02月02日
    浏览(49)
  • <html>

    在iOS开发中,经常会涉及到支付功能,这里对常见的微信支付做一下详细说明 微信开放平台(微信支付须要付费的。注冊成功后使用的主要为AppKey/SecretKey,当中SecrectKey交由后台完毕集成) 微信开放平台是商户APP接入微信支付开放接口的申请入口。通过此平台可申请微信APP支付。

    2024年02月08日
    浏览(40)
  • class<T extends interface> 或 class<T extends abstract class>

    Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。 类型通配符一般是使用 ? 代替具体的类型参数 要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends,最后紧跟它的上界

    2024年02月12日
    浏览(37)
  • 将较大的数组赋值<el-table></el-table>时,会导致页面卡顿,甚至崩溃

    遇到的问题:将长度为40的数组数据赋值el-table/el-table,我发现loading没有效果,后面发现是页面卡住了,loading直接没有出现。 经过查询资料,发现el-table会有卡顿的问题,看到有的博主推荐使用一款叫umy-ui的插件,我就试了试,发现卡顿的问题解决了。 官网: http://www.umyui

    2024年02月05日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包