std::inistializer_list
使用inistializer_list能够初始化同一类型或者能够隐式转换成统一类型的函数形参,简化函数接口的实行,例如:
double Sum(std::initializer_list<double>li) { double sum = 0.0; for(auto p = li.begin(); p != li.end(); p++) { sum += *p; } return sum; }这样调用函数的方式可以是多个参数:
cout<<Sum({1.2})<<endl; cout<<Sum({1.2, 1.3})<<endl; cout<<Sum({})<<endl;注意花括号是不能省略的。
如果不使用initializer_list则需要使用varg_list来实现变参函数:
#include <cstdarg> double Sum(int num, ...) { double sum = 0.0; va_list _v; va_start(_v, num); for (int i = 0; i < num; i++) { sum+=va_arg(_v, double); } va_end(_v); return sum; }调用例子为:
cout<<Sum(1, 1.2)<<endl; cout<<Sum(2, 1.2, 1.3)<<endl; cout<<Sum(0)<<endl;可以看出来va_list来实现需要提供一个额外的参数来告诉实现函数变参有多少个,假如给出个数的比实际输入的少,截取前面的个数进行处理,给多了按照实际的输入进行处理,不会抛出异常。
对比两个可以看出前者具有强类型校验,能够在编译期发现错误,va_list则不行,同时前者不需要提供变参个数。
这里结合模板来实现一个简单的加法器
template <typename T> T Sum(std::initializer_list<T> li) { T sum{}; for (auto p = li.begin(); p != li.end(); p++) sum += *p; return sum; }调用例子:
cout<<Sum<double>({1.2, 1.3})<<endl; cout<<Sum<double>({})<<endl;
如果编译器不支持auto关键字,请使用 std::initializer_list<double>::iterator.
decltype 与返回类型后置
没有decltype之前如果需要实现下例Sum加法器是十分困难的。
template <typename T1, typename T2> T1 Sum(T1 t1, T2 t2) { return t1 + t2; } cout<<Sum<int, double>(1, 1.2)<<endl; cout<<Sum<double, int>(1.2, 1)<<endl;输出结果不一样,前者是整数2,后者是2.2。
使用新语法将函数的返回类型放置到参数列表后面:
template <typename T1, typename T2> auto Sum(T1 t1, T2 t2) -> decltype(t1 + t2) { return t1 + t2; }
智能指针
智能指针