模板函数-特化的重载;
如果函数无参,编译器无法推断,此时应:
add<int>();//手动给定模板参数类型
模板参数用于编译器优化:
1.整型可以作为模板参数:
template<int N>
void show_times(std::string msg){
for(int i=0;i<N;i++){
std::cout<<msg<<std::endl;
}
}
int main(){
show_times<2>("two");
}
为什么要这么做?
优点:
此时传入的N会作为编译期常量,对每个不同的N,编译器会单独生成代码,进而进行优化。
而仅仅作为函数参数传入时,N是运行期常量,编译器无法自动优化。
缺点:
编译器会根据N的不同生成很多份代码--二进制文件大小剧增,编译变慢。
2.模板参数用于判断语句:
将判断语句参数改成模板参数。在编译时会生成两份代码,对于不执行的情况会直接优化掉。防止了运行时开销。
template<bool debug>
int sum(int n){
int res=0;
if(debug){
...
}
int main(){
sum<true>(3);
sum<false>(2);
...
}
自动类型推导auto
注意:无法用于类变量
inline关键字已经没用了,现在是由编译器来决定释放内联;
常引用不仅更加安全,且编译器也能大胆放心去优化。
右值:
不长时间存在于内存中的值,例如一些常值表达式;
此外,C++规定int&&能自动转化为const int&;
自动类型推导:万能推导(decltype(auto))
decltype与auto的区别:
1.auto类型说明符用编译器计算变量的初始值来推断其类型,而decltype虽然也让编译器分析表达式并得到它的类型,但是不实际计算表达式的值。
2.编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。
3.与auto不同,decltype的结果类型与表达式形式密切相关,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。
在代理模式中,用于完美转发函数的返回值:
#include<iostream>
#include<vector>
using namespace std;
template<class T1,class T2>
auto add(const std::vector<T1>&a,const std::vector<T2>&b){
using T0=decltype(T1{}+T2{});//创建T1类型和T2类型的0值对象,用于类型推导;
std::vector<T0>ret;
for(size_t i=0;i<std::min(a.size(),b.size());i++){
ret.push_back(a[i]+b[i]);
}
return ret;
}
int main(){
std::vector<int>a={2,3,4};
std::vector<float>b={0.5f,1.0f,2.0f};
auto c=add(a,b);
for(const auto&i:c)
std::cout<<i<<endl;
return 0;
}
using 创建类型别名,和typedef等价
函数式编程
函数也可作为另一个函数的参数,实际传参就是函数指针
template<class T>
void call_Fun(T fun){
fun(0);
fun(1);
}
int main(){
call_Fun((auto n){return n*n;});//Lambad参数为auto就可以等价于模板函数;
}
异步编程
匿名递归
总结:
lambda作为参数:用template<classFunc>然后Funcconst&做类型。
lambda作为返回值:用auto做类型。
牺牲性能但存储方便:std::function容器。
lambda作为参数:通常用[&]存储引用。
lambda作为返回值:总是用[=]存储值。
tuple
int main(){
auto tup=std::tuple<int,float,char>{3,3.14f,'h'};
auto first=std::get<0>(tup);//可以使用std::get来解包;
auto second=std::get<1>(tup);
auto third=std::get<2>(tup);
//也可以使用结构化绑定语法;
auto[x,y,z]=tup;
std::cout<<x<<endl;
std::cout<<y<<endl;
std::cout<<z<<endl;
}
结构化绑定也可以用于自定义类//C++ 17
class Test{
public:
Test(int _x,string _s):n(_x),s(_s){};
void add(int i,int j){
std::cout<<i+j<<endl;
}
int n;
string s;
};
int main(){
Test t(1,"hello world!");
auto [x,y]=t;
std::cout<<x;
}
tuple的另一个用法是返回多个返回值!