当前位置: 首页 > news >正文

婚纱摄影网站模板之家云南最大的互联网公司

婚纱摄影网站模板之家,云南最大的互联网公司,做ppt常用的网站有哪些,seo搜索优化类型分类 C11以后,进一步对类型进行了划分,右值被划分为纯右值(pure value,简称prvalue)和将亡值(expiring value,简称xvalue)。纯右值是指那些字面值常量或求值结果相当于字面值或…

类型分类

  • C++11以后,进一步对类型进行了划分,右值被划分为纯右值(pure value,简称prvalue)和将亡值(expiring value,简称xvalue)。
  • 纯右值是指那些字面值常量或求值结果相当于字面值或是一个不具名的临时对象。如:truenullptr,或者类似42str.substr(1, 2)str1 + str2、传值返回的函数调用,或者a++a + b等。纯右值和将亡值是C++11中提出的,C++11中的纯右值概念划分等价于C++98中的右值。
  • 将亡值是指返回右值引用的函数的调用表达式和转换为右值引用的转换函数的调用表达式,如move(x)static_cast<X&&>(x)
  • 泛左值(generalized value,简称glvalue),泛左值包含将亡值和左值。
  • 值类别的详细定义可以参考cppreference.com和Value categories这两个关于值类别的中文和英文的官方文档,有兴趣可以了解细节。

引用折叠

  • 在C++中,不能直接定义引用的引用如int& && r = i;,这样写会直接报错,通过模板或typedef中的类型操作可以构成引用的引用。
  • 通过模板或typedef中的类型操作可以构成引用的引用时,这时C++11给出了一个引用折叠的规则:右值引用的右值引用折叠成右值引用,所有其他组合均折叠成左值引用。
  • 下面的程序中很好地展示了模板和typedef时构成引用的引用时的引用折叠规则。
  • 像f2这样的函数模板中,T&&x参数看起来是右值引用参数,但是由于引用折叠的规则,他传递左值时就是左值引用,传递右值时就是右值引用,有些地方也把这种函数模板的参数叫做万能引用。
  • Function(T&&t)函数模板程序中,假设实参是int右值,模板参数T的推导int,实参是int左值,模板参数T的推导int&,再结合引用折叠规则,就实现了实参是左值,实例化出左值引用版本形参的Function,实参是右值,实例化出右值引用版本形参的Function。
 //由于引用折叠限定,f1实例化以后总是一个左值引用
template<class T>
void f1(T& x)
{}// 由于引用折叠限定,f2实例化后可以是左值引用,也可以是右值引用
template<class T>
void f2(T&& x)
{}int main()
{/*int i = 0;int&&& r = i;*/typedef int& lref;//typedef int&& rref;using rref = int&&;int n = 0;// 引用折叠lref& r1 = n; // r1 的类型是 int&lref&& r2 = n; // r2 的类型是 int&rref& r3 = n; // r3 的类型是 int&rref&& r4 = 1; // r4 的类型是 int&&// 没有折叠->实例化为void f1(int& x)f1<int>(n);f1<int>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&>(n);f1<int&>(0); // 报错// 折叠->实例化为void f1(int& x)f1<int&&>(n);f1<int&&>(0); // 报错// 折叠->实例化为void f1(const int& x)f1<const int&>(n);f1<const int&>(0);// 折叠->实例化为void f1(const int& x)f1<const int&&>(n);f1<const int&&>(0);// 没有折叠->实例化为void f2(int&& x)f2<int>(n); // 报错f2<int>(0);// 折叠->实例化为void f2(int& x)f2<int&>(n);f2<int&>(0); // 报错// 折叠->实例化为void f2(int&& x)f2<int&&>(n); // 报错f2<int&&>(0);return 0;
}

万能引用

上面代码中的第二个模板其实就是万能引用的模板,模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。比如:

template<class T>
void Function(T&& t)
{//...
}

右值引用和万能引用的区别就是,右值引用需要是确定的类型,而万能引用是根据传入实参的类型进行推导,如果传入的实参是一个左值,那么这里的形参t就是左值引用,如果传入的实参是一个右值,那么这里的形参t就是右值引用。

  • 如果传入一个左值A,模板参数 T 被推导为 A&

  • 如果传入一个右值A,模板参数 T 被推导为 A

// 万能引用
template<class T>
void Function(T&& t)
{int a = 0;T x = a;//x++;cout << &a << endl;cout << &x << endl << endl;
}int main()
{// 10是右值,推导出T为int,模板实例化为void Function(int&& t)Function(10); // 右值int a;// a是左值,推导出T为int&,引用折叠,模板实例化为void Function(int& t)Function(a); // 左值// std::move(a)是右值,推导出T为int,模板实例化为void Function(int&& t)Function(std::move(a)); // 右值const int b = 8;// b是左值,推导出T为const int&,引用折叠,模板实例化为void Function(const int&t)// 所以Function内部会编译报错,x不能++Function(b); // const 左值// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&&t)// 所以Function内部会编译报错,x不能++Function(std::move(b)); // const 右值return 0;
}

为什么需要转发?

下面重载了四个Fun函数,这四个Fun函数的参数类型分别是左值引用、const左值引用、右值引用和const右值引用。在主函数中调用Function函数时分别传入左值、右值、const左值和const右值,在Function函数中再调用Func函数。如下:

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
template<class T>
void Function(T&& t)
{Fun(t);
}int main()
{int a = 10;Fun(a);       //左值Fun(move(a)); //右值const int b = 20;Fun(b);       //const 左值Fun(move(b)); //const 右值return 0;
}

由于Function函数的参数类型是万能引用,因此既可以接收左值也可以接收右值,而我们在Function函数中调用Fun函数,就是希望调用Function函数时传入左值、右值、const左值、const右值,能够匹配到对应版本的Fun函数。

  • 但实际调用Function函数时传入左值和右值,最终都匹配到了左值引用版本的Fun函数,调用Function函数时传入const左值和const右值,最终都匹配到了const左值引用版本的Fun函数。
  • 根本原因就是,上面的模板中Fun(t)参数中虽然t是右值引用,但别忘了上一篇博客我们说过右值引用变量属于左值。你传进去的参数t是左值,并且不要以为把t改为move(t)就可以解决问题,实际上还是差不多,改变后全变成右值引用而达不到我们期望的那样。

也就是说,右值经过一次参数传递后其属性会退化成左值,如果想要在这个过程中保持右值的属性,就需要用到完美转发。

这就是“转发问题”:如何在模板函数中保持参数原始的值类别(左值/右值)和const/volatile属性,并将其原封不动地传递给下一个函数?

完美转发

要想在参数传递过程中保持其原有的属性,需要在传参时调用forward函数。比如:

// 万能引用
template<class T>
void Function(T&& t)
{Fun(forward<T>(t));
}
  • Function(T&& t)函数模板程序中,传左值实例化以后是左值引用的Function函数,传右值实例化以后是右值引用的Function函数。
  • 但是结合我们在上篇博客的讲解,变量表达式都是左值属性,也就意味着一个右值被右值引用绑定后,右值引用变量表达式的属性是左值,也就是说Function函数中t的属性是左值,那么我们把t传递给下一层函数Fun,那么匹配的都是左值引用版本的Fun函数。这里我们想要保持t对象的属性,就需要使用完美转发实现。
template <class T> T&& forward (typename remove_reference<T>::type& arg);
  • 完美转发forward本质是一个函数模板,他主要还是通过引用折叠的方式实现,下面示例中传递给Function的实参是右值,T被推导为int,没有折叠,forward内部t被强转为右值引用返回;传递给Function的实参是左值,T被推导为int&,引用折叠为左值引用,forward内部t被强转为左值引用返回。

完美转发的使用场景

// 万能引用
template<class T>
void Function(T&& t)
{Fun(forward<T>(t));
}int main()
{// 10是右值,推导出T为int,模板实例化为void Function(int&& t)Function(10); // 右值int a;// a是左值,推导出T为int&,引用折叠,模板实例化为void Function(int& t)Function(a); // 左值// std::move(a)是右值,推导出T为int,模板实例化为void Function(int&& t)Function(std::move(a)); // 右值const int b = 8;// b是左值,推导出T为const int&,引用折叠,模板实例化为void Function(const int&t)Function(b);// std::move(b)右值,推导出T为const int,模板实例化为void Function(const int&& t)Function(std::move(b)); // const 右值return 0;
}

完美转发的原理

template<typename T>
T&& forward(typename std::remove_reference<T>::type& arg) noexcept {return static_cast<T&&>(arg);
}
  1. typename std::remove_reference<T>::type& arg: 这一部分确保 arg 总是一个左值引用。

  2. static_cast<T&&>(arg): 这是核心。转换的结果取决于 T 的推导类型。

当传入左值时:

  • T 被推导为 MyType&

  • T&& 经过引用折叠后是 MyType& && -> MyType&

  • static_cast<MyType&>(arg): 将一个左值转换为左值引用,什么也不做,返回的依然是左值。

当传入右值时:

  • T 被推导为 MyType

  • T&& 就是 MyType&&

  • static_cast<MyType&&>(arg): 将一个左值 arg 强制转换为右值引用。这正是 std::move 的行为。

结论std::forward<T>(arg) 做的事情是:如果原始传入的参数是右值,它就将 arg 转换为右值;如果原始传入的参数是左值,它就什么都不做,让 arg 保持为左值。它完美地“转发”了参数的值类别。

扩展思路

理解了完美转发的原理,其实如果你读过我list底层实现这篇博客,你会发现我们在实现list底层const迭代器和非const迭代器时,也是利用相似的原理​。核心思想都是通过模板参数和类型推导,让编译器自动生成不同版本的代码。

http://www.dtcms.com/a/596018.html

相关文章:

  • 做外贸网站格式wordpress延迟加载js
  • 海阳有没有做企业网站的做搜索引擎优化对网站有哪些好处
  • 网站开发价格婚礼礼网站如何做的
  • 厨具 技术支持东莞网站建设网站开发前端与后端区别
  • 游戏网站有哪些wordpress 分享
  • 制作华为手机网站建设规划书业余学做衣服上哪个网站
  • 深圳建设网站公司简介a站为什么会凉
  • 网站建设试题及答案企业信息公示管理系统官网
  • 网站授权协议中企动力做网站多久能好
  • 电商网站费用品牌建设 凝心
  • 专业网站开发哪里找营销网站建设哪家便宜
  • 提供零基础网站建设教学保险网站哪家好
  • wordpress无法设置主页浙江seo外包
  • 茂名企业做网站织梦做第一个网站
  • 一键生成100个原创视频如何做seo优化
  • 那个网站是做房产中介的新手学做网站72小时精选
  • 我要建个人网站合肥专业网站制作团队
  • 公司网站经常打不开建设银行可以查房贷的网站
  • 有哪些公司网站建设比较好室内设计作品集案例赏析
  • 韩国展厅设计网站汽车做网站
  • 下载的asp网站怎么打开网站建设与维护实训心得
  • 南城网站建设价格wordpress带用户中心主题
  • 网站制作案例价格网站的类型大全
  • 图片代码如何做网站怎么发帖子做推广
  • 免费网页游戏网站做网站跳转怎么收费
  • 局网站建设意见重庆市住建厅网站
  • 济南企业营销型网站建设个人网站 组建
  • 高端企业网站公司自学网站建设最快要多久
  • 网站建设与管理课程项目公众号小程序搭建
  • 美容院网站建设方案书厦门百度seo排名