期货交易网站开发,企业网络营销信息源类别及传递渠道调查,一个人能开发app吗,国外的优秀网站我们知道#xff0c;C中有左值引用和右值引用#xff0c;首先我们要知道什么是左值什么是右值。 左值#xff1a;表达式结束后依然存在的持久对象。左值可以出现在赋值语句的左边或右边。例如#xff0c;变量和函数返回的引用都是左值。左值通常有持久的地址#xff0c;可… 我们知道C中有左值引用和右值引用首先我们要知道什么是左值什么是右值。 左值表达式结束后依然存在的持久对象。左值可以出现在赋值语句的左边或右边。例如变量和函数返回的引用都是左值。左值通常有持久的地址可以被取地址操作符 获取地址。 右值通常是临时的不能有多个引用它们不指向持久存储。右值可以出现在赋值语句的右边但不能出现在左边。字面量如 42 或 hello和将亡值函数返回的非引用类型都是右值。右值通常用于描述临时对象或字面值它们在使用后很快就会被销毁。 那么在将左值引用和右值引用传入函数的时候我们有时候需要保存它的左值属性或者右值属性这时就需要分别写出左值引用和右值引用函数重载。我们也可能需要将不同类型的参数传入函数这时候就需要用到函数模板。
函数重载如下
void func(int n){cout 左值 n endl;
}void func(int m){cout 右值 m endl;
}
函数模板如下
//第一种函数模板
templateclass T
void func(T n){cout 左值 n endl;
}
templateclass T
void func(T m){cout 右值 m endl;
}//第二种函数模板
void func(int n){cout 左值 n endl;
}
void func(int m){cout 右值 m endl;
}
void func(double n){cout 左值double n endl;
}
void func(double m){cout 右值double m endl;
}templateclass T
void revoke(T t){func(t);
} 第一种能正确输出左右值但是它并不能对不同类型的参数调用不同操作不符合多态假如你想要int类型的参数打印int想要double类型的参数打印double第一种函数无法实现。 第二种不能正确输出左右值全部都走到左值因为t是一个左值变量只会被转发到左值函数中。 综上只有用完美转发才能实现既识别左右值又能对不同类型的参数调用不同操作。 通过forward()实现完美转发
void func(int n){cout 左值int n endl;
}
void func(int m){cout 右值int m endl;
}
void func(double n){cout 左值double n endl;
}
void func(double m){cout 右值double m endl;
}templateclass T
void revoke(T t){func(forwardT(t));
}int main(){int i 10;int n i;int m 100;m 10;//只能识别左右值不能根据参数类型选择不同操作// func(n);// func(static_castint(m));//正确推导revoke(static_castint(n));revoke(static_castint(m));revoke(n);revoke(move(m)); //移动语义将m的内容移动给一个临时变量此时传递的是将亡值会被识别成右值。move之后m的资源被转移不应该再次使用mdouble d 1.1;double dn d;double dm 10.10;revoke(static_castdouble(dn));revoke(static_castdouble(dm));// //err -- 全部是左值// revoke(n);// revoke(m);// //err -- 全部是右值// revoke(static_castint(n));// revoke(static_castint(m));return 0;
}
输出如下 走到这里又引出三个问题。1.T是什么 2.forward原理 3.为什么要强转
1.T是什么 有个东西叫引用折叠 引用折叠的规则 如果两个引用中至少有一个是左值引用那么结果是左值引用 如果两个引用都是右值引用那么结果是右值引用 比如我们int 那么它会引用折叠变成int int 会变成int 引用折叠和模板很像模板识别参数类型引用折叠识别引用类型。比如我们templateclass T那么输入int就会识别成int输入double就会识别成double。在引用折叠下输入什么值引用就会识别成什么值引用。 2.forward原理 forward用于保持原参数的类型比如我是int就保持int在第二种函数模板中我们已经说过了如果不保持原参数的类型那么t就是一个左值变量会全部走到左值 3.为什么要强转 查看完美转发的代码可以发现有两个错误示例 //err -- 全部是左值revoke(n);revoke(m);//err -- 全部是右值revoke(static_castint(n));revoke(static_castint(m)); 第一个 -- 在函数调用时如果你直接传递一个具名变量无论它是通过左值引用还是右值引用声明的该变量作为参数传递给函数时总是作为左值传递的。如果我们不强转那么会被识别左值这里的强转实际上是告诉函数我想要传递的类型是什么 第二个 -- 当一个A类型变量强转为B类型时实际上是创建了一个B类型的匿名对象来接收一个A类型的变量的值而匿名对象是右值将亡值并且它不具名所以会被识别成右值只有具名变量才会默认作为左值传递