做网站微信公众号,怎么做国外网上生意,没有做防注入的网站,说一说网站建设的含义完美转发 
1 概念 
首先解释一下什么是完美转发#xff0c;它指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美#xff0c;即不仅能准确地转发参数的值#xff0c;还能保证被转发参数的左、右值属性不变。 
templatetypename T
void fu…完美转发 
1 概念 
首先解释一下什么是完美转发它指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美即不仅能准确地转发参数的值还能保证被转发参数的左、右值属性不变。 
templatetypename T
void function(T t) {otherdef(t);
}function() 函数模板中调用了 otherdef() 函数。在此基础上完美转发指的是如果 function() 函数接收到的参数 t 为左值那么该函数传递给 otherdef() 的参数 t 也是左值反之如果 function() 函数接收到的参数 t 为右值那么传递给 otherdef() 函数的参数 t 也必须为右值。 
2 C98实现完美转发 C98通过左值引用和常量左值引用函数重载实现完美转发  C98/03 标准下的 C 也可以实现完美转发只是实现方式比较笨拙。通过前面的学习我们知道C 98/03 标准中只有左值引用并且可以细分为非 const 引用和 const 引用。其中使用非 const 引用作为函数模板参数时只能接收左值无法接收右值而 const 左值引用既可以接收左值也可以接收右值但考虑到其 const 属性除非被调用函数的参数也是 const 属性否则将无法直接传递。  如果使用 C 98/03 标准下的 C 语言我们可以采用函数模板重载的方式实现完美转发  
#include iostream
using namespace std;
//重载被调用函数查看完美转发的效果
void otherdef(int  t) {cout  lvalue\n;
}
void otherdef(const int  t) {cout  rvalue\n;
}
//重载函数模板分别接收左值和右值
//接收右值参数
template typename T
void function(const T t) {otherdef(t);
}
//接收左值参数
template typename T
void function(T t) {otherdef(t);
}
int main()
{function(5);//5 是右值int  x  1;function(x);//x 是左值return 0;
}
// 程序执行结果为
// rvalue
// lvalue从输出结果中可以看到对于右值 5 来说它实际调用的参数类型为 const T 的函数模板由于 t 为 const 类型所以 otherdef() 函数实际调用的也是参数用 const 修饰的函数所以输出“rvalue”对于左值 x 来说2 个重载模板函数都适用C编译器会选择最适合的参数类型为 T 的函数模板进而 therdef() 函数实际调用的是参数类型为非 const 的函数输出“lvalue”。 
3 C 11实现完美转发。 
C 11 标准中允许在函数模板中使用右值引用来实现完美转发 
万能引用规则 C11 标准中规定通常情况下右值引用形式的参数只能接收右值不能接收左值。但对于函数模板中使用右值引用语法定义的参数来说它不再遵守这一规定既可以接收右值也可以接收左值此时的右值引用又被称为“万能引用”  在 C11 标准中实现完美转发只需要编写如下一个模板函数即可  
template typename T
void function(T t) {otherdef(t);
}引用折叠规则 此模板函数的参数 t 既可以接收左值也可以接收右值。但仅仅使用右值引用作为函数模板的参数是远远不够的还有一个问题继续解决即如果调用 function() 函数时为其传递一个左值引用或者右值引用的实参。  C 11标准为了更好地实现完美转发特意为其指定了新的类型匹配规则又称为引用折叠规则假设用 A 表示实际传递参数的类型: 当实参为左值或者左值引用A时函数模板中 T 将转变为 AA   A当实参为右值或者右值引用A时函数模板中 T 将转变为 AA   A。  
int n  10;
int  num  n;
function(num); // T 为 int
int  num2  11;
function(num2); // T 为 int Foward模板函数 
引入了一个模板函数 forword()我们只需要调用该函数将函数模板接收到的形参连同其左、右值属性一起传递给被调用的函数呢 
#include iostream
using namespace std;
//重载被调用函数查看完美转发的效果
void otherdef(int  t) {cout  lvalue\n;
}
void otherdef(const int  t) {cout  rvalue\n;
}
//实现完美转发的函数模板
template typename T
void function(T t) {otherdef(forwardT(t));
}
int main()
{function(5);int  x  1;function(x);return 0;
}
// 程序执行结果为
// rvalue
// lvalue总的来说在定义模板函数时我们采用右值引用的语法格式定义参数类型由此该函数既可以接收外界传入的左值也可以接收右值其次还需要使用 C11 标准库提供的 forword() 模板函数修饰被调用函数中需要维持左、右值属性的参数。由此即可轻松实现函数模板中参数的完美转发。 
1 问题定义 
完美转发就是将函数实参以其原本的值类别转发出去。转发值类别 
void foo(int )  { std::cout  lvalue  std::endl; }
void foo(int ) { std::cout  rvalue  std::endl; }
templatetypename /*T*/ void bar(/*T*/ x) { /*call foo with x*/ }int main() {int i;bar(i);  // expecting output: lvaluebar(1);  // expecting output: rvalue
}在这里变量 i 经历了两次转发所以我们需要先后解决这两次转发的值类别问题。 用户调用 bar 时参数的值类别问题当用户以左值表达式调用 bar 时确保其实例化(Instantiation)的形参类型为左值引用当用户以右值表达式调用 bar 时确保其实例化的形参类型为右值引用。 bar 调用 foo 时参数的值类别问题 当 bar 的形参类型为左值引用时将其以左值转发给 foo当 bar 的形参类型为右值引用时将其以右值转发给 foo  C 通过转发引用来解决第一个匹配通过 std::forward 来解决第二个匹配。 2 转发引用 
原理 
转发引用基于一个叫做引用坍缩(Reference Collapsing)的原理 rvalue reference to rvalue reference collapses to rvalue reference, all other combinations form lvalue reference.typedef int lref; typedef int rref;
int n;
lref  r1  n; // type of r1 is int ,  int      int 
lref r2  n; // type of r2 is int ,  int     int 
rref  r3  n; // type of r3 is int ,  int     int 
rref r4  1; // type of r4 is int,  int    int 举例说明 
void foo(int )  { std::cout  lvalue  std::endl; }
void foo(int ) { std::cout  rvalue  std::endl; }
templatetypename T int bar(T x);  // x is a forwarding referenceint main() {int i  1;int lref  i;int rref  1;bar(1);                 // T 为 int,   decltype(x) 为 intbar(i);                 // T 为 int,  decltype(x) 为 intbar(lref);              // T 为 int,  decltype(x) 为 intbar(rref);              // T 为 int,  decltype(x) 为 intbar(std::move(rref));   // T 为 int,   decltype(x) 为 intbarint (1);         // T 为 int, decltype(x) 为 int
}第一步转发问题解决 
解决了调用 bar 时参数值类别的问题现在我们将 bar 的参数传递给 
foovoid foo(int )  { std::cout  lvalue  std::endl; }
void foo(int ) { std::cout  rvalue  std::endl; }
templatetypename T int bar(T x) { foo(x); }3 forward转发 
forward原理 
std::forward 的实现如下 
templatetypename _Tp
constexpr _Tp
forward(typename std::remove_reference_Tp::type __t) noexcept
{ return static_cast_Tp(__t); }templatetypename _Tp
constexpr _Tp
forward(typename std::remove_reference_Tp::type __t) noexcept
{static_assert(!std::is_lvalue_reference_Tp::value, template argument substituting _Tp is an lvalue reference type);return static_cast_Tp(__t);
}实现了将左值转发为左值或右值将右值转发为右值。 
举例说明 
void foo(const int )  { std::cout  lvalue  std::endl; }
void foo(const int ) { std::cout  rvalue  std::endl; }int main() {int i  1;foo(std::forwardint(i));     // output: rvalue; forward lvalue - rvaluefoo(std::forwardint(i));    // output: lvalue; forward lvalue - lvaluefoo(std::forwardint(i));   // output: rvalue; forward lvalue - rvaluefoo(std::forwardint(1));     // output: rvalue; forward rvalue - rvaluefoo(std::forwardint(1));    // error: static_assert failed due to requirement !is_lvalue_referenceint ::value can not forward an rvalue as an lvaluefoo(std::forwardint(1));   // output: rvalue; forward rvalue - rvalue
}第二步转发的实现 
void foo(int )  { std::cout  lvalue  std::endl; }
void foo(int ) { std::cout  rvalue  std::endl; }
templatetypename T int bar(T x) { foo(std::forwardT(x)); }int main() {int i  1;bar(i);  // output: lvaluebar(1);  // output: rvalue
}我们总结一下。完美转发问题是将函数的参数以其原本值类别转发出去的问题。转发引用 和 std::forward 共同解决了完美转发问题。其中转发引用将函数的左值实参推导为左值引用类型右值实参推导为右值引用类型。std::forward 将左值引用类型的实参转发为左值将右值引用类型的实参转发为右值。