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

跟老外做网站国内十大erp系统

跟老外做网站,国内十大erp系统,网页设计教程博主,山西网站建设开发模板中的右值引用(万能引用)、引用折叠与完美转发 文章目录 模板中的右值引用(万能引用)、引用折叠与完美转发一、万能引用与引用折叠1. 模板中的右值引用2. 自动类型推导(auto)与万能引用3. 引用折叠与万能引用4. lambda表达式捕…

模板中的右值引用(万能引用)、引用折叠与完美转发

文章目录

  • 模板中的右值引用(万能引用)、引用折叠与完美转发
    • 一、万能引用与引用折叠
      • 1. 模板中的右值引用
      • 2. 自动类型推导(auto)与万能引用
      • 3. 引用折叠与万能引用
      • 4. lambda表达式捕获
      • 5. 条件转发
      • 6. 类型萃取
    • 二、完美转发
    • 总结

一、万能引用与引用折叠

1. 模板中的右值引用

​ 我们经常听万能引用,什么是万能引用,与普通的右值引用有什么区别?

下面给出一个案例,利用模板函数参数中的右值引用来展现万能引用的用途:

首先给出一个自定义的类型,简易的实现出拷贝构造函数和移动构造函数同时不必关注是否正常实现了功能,增加打印信息以便我们可以通过控制台明晰该函数是否被调用,何时被调用:

class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}Date(const Date& d){cout << "Date(const Date& d)" << endl;}Date(Date&& d){cout << "Date(Date&& d)" << endl;}
private:int _year;int _month;int _day;
};

接着给出两个测试函数,函数参数类型分别常量左值引用和右值引用:

// 常量左值引用函数模板
template<typename T>
void func1(const T& val)
{T d(val);
}
// 万能引用参数函数模板
template<typename T>
void func2(T&& val)
{T d(std::forward<T>(val));cout << "val是右值引用:" << std::is_rvalue_reference<decltype(val)>::value << endl;
}

注意上面 func2() 函数中用到的 forward() 相当于 move() 的进阶版,可以保证在函数间参数传递时保持原有左/右值类型。

继续给出测试用例:

Date d(2000, 1, 2);cout << "*********左值参数********" << endl;
func1(d);
cout << "*************************" << endl;
func2(d);cout << "*********右值参数********" << endl;
func1(std::move(d));
cout << "*************************" << endl;
func2(std::move(d));

运行结果:

在这里插入图片描述

通过上图我们认识到万能引用在模板中的重要性,万能引用是模板中大多数情况保证移动构造函数被正常调用的重要条件。只有参数是万能引用时,函数内部才可调用 std::forward<T>() 完美转发变量的左右值类型,并将保持源类型的变量转发给其他函数。

至于我们为什么称其为“万能引用”,虽然常量左值引用 “const T& val” 也能兼容接收左值和右值参数,但它不支持移动语义,因为它不允许修改绑定的对象因此,万能引用更有优势,因为它既支持移动语义,又能与完美转发结合使用,成功传递变量及其类型。

2. 自动类型推导(auto)与万能引用

当使用auto关键字时,万能引用可以帮助推导变量的类型。例如,auto&&可以根据初始化表达式是左值还是右值来推导出正确的类型。

void test2()
{Date d(2000, 1, 2);auto&& d1(d);cout << "d1是左值引用:" << std::is_lvalue_reference<decltype(d1)>::value << endl;cout << "d1是右值引用:" << std::is_rvalue_reference<decltype(d1)>::value << endl;auto&& d2(std::move(d));cout << "d2是左值引用:" << std::is_lvalue_reference<decltype(d2)>::value << endl;cout << "d2是右值引用:" << std::is_rvalue_reference<decltype(d2)>::value << endl;
}

在这里插入图片描述

通过上图我们发现 auto&& 可以在推导表达式类型时,同时推导其左值性或右值性。

3. 引用折叠与万能引用

引用折叠的规则解决了引用的引用(C++中不允许)的问题。这里是引用折叠的基本规则:

  • 如果两个引用中至少一个是左值引用(&),那么结果是左值引用(&)。
  • 如果两个引用都是右值引用(&&),那么结果是右值引用(&&)。

首先给出一个简单的以万能引用为参数的模版函数:

template<typename T>
void func(T&& val) {// val 是一个万能引用auto p = &val;cout << "左值引用:" << std::is_lvalue_reference<decltype(val)>::value << endl;cout << "右值引用:" << std::is_rvalue_reference<decltype(val)>::value << endl;
}

测试函数:

void test3()
{int x = 10;int& lx = x; // lx 是 x 的左值引用int&& rx = 10; // rx 是一个右值引用func(x);  // T 推导为 int&,因此 val 的类型为 int& &,折叠为 int&cout << "x是右值引用:" << std::is_rvalue_reference<decltype(x)>::value << endl;cout << "-------------------" << endl;func(lx); // T 推导为 int&,因此 val 的类型为 int& &,折叠为 int&cout << "lx是右值引用:" << std::is_rvalue_reference<decltype(lx)>::value << endl;cout << "-------------------" << endl;func(rx); // T 推导为 int&&,因此 val 的类型为 int&& &&,折叠为 int&&cout << "xr是右值引用:" << std::is_rvalue_reference<decltype(rx)>::value << endl;cout << endl;func(move(x));cout << "move(x)是右值引用:" << std::is_rvalue_reference<decltype(move(x))>::value << endl;cout << "-------------------" << endl;func(10); // T 推导为 int,因此 val 的类型为 int&&
}

运行结果:

在这里插入图片描述

对上面运行结果部分地方需要着重做出解释:

在这里插入图片描述

4. lambda表达式捕获

void test4()
{auto x = 5;auto lambda = [y = std::move(x)]() mutable {y += 2;return y;};cout << x << endl;cout << lambda() << endl;
}

当调用 lambda() 时,将输出 7,因为 y 被初始化为 5 并且增加了 2。请注意,由于 x 被移动到 yx 的值在移动后未定义,但通常在实际编译器实现中,基本类型的值在移动后保持不变。因此,输出 x 的值仍然是 5。

5. 条件转发

template<typename T>
void forwarder(T&& arg) {if constexpr (std::is_lvalue_reference_v<T>) {//process(arg); // 处理左值}else {//process(std::move(arg)); // 处理右值}
}

在这个例子中,forwarder 函数使用万能引用 T&& 来接受任何类型的参数,并根据参数的类型来决定调用哪个 process 函数。

6. 类型萃取

类型萃取(Type Traits)是模板元编程中的一种技术,它允许你在编译时检查类型信息或者修改类型。万能引用可以与类型萃取结合使用,以确定传递给模板的参数类型的属性。

template<typename T>
void process(T&& arg) {using Type = typename std::remove_reference<T>::type;if constexpr (std::is_integral_v<Type>) {// 如果 T 是整数类型//handle_integral(std::forward<T>(arg));}else {// 如果 T 不是整数类型//handle_non_integral(std::forward<T>(arg));}
}

在这个例子中,process 函数使用类型萃取来移除引用,并检查 T 是否为整数类型。然后它使用 std::forward 来保持参数的值类别,并将其传递给相应的处理函数。

二、完美转发

在这里插入图片描述

​ 实际上这里才真正提起完美转发这个概念,看了本文前面内容也已经大概了解,我们这里仅仅将其抽离出来进行特别总结。

  • 首先,我们已经知道右值引用变量具有左值属性,因为其需要保留可修改性,所以自然不能是右值。

  • 其次,传递给右值引用类型的参数在传参后会退化为左值

所以我们想要在万能引用作参数的函数内部实现分离操作,需要对参数的左右值属性进行判断,例如:

template<typename T>
void print_right(T&& v)
{cout << "right -> " << v << endl;
}
template<typename T>
void print_left(const T& v)
{cout << "left -> " << v << endl;
}template<typename T>
void do_something(T&& val)
{if (std::is_rvalue_reference<decltype(val)>::value)	// val是右值{print_right(std::forward<T>(val));	// 利用完美转发将退化逆向为初始类型,此处判断初始右值,也可 move(val)}else	// val是左值{print_left(val);		// val退化为左值,直接传递}
}

测试函数:

void test5()
{int x = 18;//do_something<int>(x);		// 编译报错do_something<int&>(x);	// 注意这里x是左值,所以模板参数为int编译会报错,模板参数和函数参数类型需要统一满足引用折叠do_something<int>(10);
}

注意上面测试代码的案例也是引用折叠的重要体现

对于完美转发 forward(val) 中 val 的属性可能是左值也可能是右值:

  • 当 val 是左值时,forward 对左值 val 不做处理
  • 当 val 是右值时,forward 的作用相当于 move(val)

在这里插入图片描述


总结

​ 本文被三个词语所贯穿:万能引用、引用折叠、完美转发。这三个概念之间的联系紧密以及使用场景高度重合,正是因为C++11中提出如此富有意义的新概念,极大地方便了我们重构代码,理想高效地编码实现功能。

http://www.yayakq.cn/news/988092/

相关文章:

  • 做一个企业网站大概需要多少钱中国企业信用网
  • 网站后端架构如何做城市建设杂志社网站
  • 自己公司设计一个网站网页海报设计教程
  • 沈阳专业做网站宝应县建设工程管理局网站
  • 芜湖建设路小学网站小型手机网站建设推荐
  • 漯河网站建设lhwzzz怎样制作网站积分系统
  • 简约好看的网站模板网站什么也没动怎么不收录啦
  • 企业网站开发报价河北seo推广方法
  • 做网站建设的基本步骤职友集 一家做公司点评的网站
  • 华建河北住房和城乡建设厅网站合肥网站建设价格
  • 网站做cdn需要多少钱都匀住房与城乡建设部网站
  • 怀远网站建设移动端是指手机吗
  • 大连模板网站制作公司电话做网站免费空间
  • 做网站后台要学昆山建设信息网站
  • 中国有哪些跨境电商平台北京首页关键词优化
  • 传世网站建设成都营销型网站设计
  • 成功案例 品牌网站如何设置自己的网址
  • 营销网站seo推广网站开发有哪些职位
  • 东庄水利枢纽建设公司网站网站开发的自适应
  • 优惠券网站怎么做的做农村网站多少钱
  • 手机如何制作自己的网站给网站做
  • 白云网站制作高校学校网站建设
  • 网站举报能不能查到举报人网络营销策划的流程及要点
  • 广东网站设计哪家专业浅析网站域名在搜索引擎排名中的作用
  • 常德网站建设多少钱海外红人营销推广
  • 用织梦系统做网站产权查询一个网站是用什么系统做的
  • 网站建设 岗位做网站需要注意的地方
  • 万网个人网站建设教程开发公司经理述职报告
  • .net网站模版seo培训班
  • 电子商务网站的基础建设湖南十大传媒公司