冒用网站备案号建设网站,小程序设计需要多少钱,网站模版 源码之家,ui界面设计素材目录 一、可变模板参数的概念及功能
1.1Args的概念与使用
1.2获取args中的参数
二、emplace可变模板参数的实际应用
三、逗号表达式展开参数包 一、可变模板参数的概念及功能
1.1Args的概念与使用 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板…目录 一、可变模板参数的概念及功能
1.1Args的概念与使用
1.2获取args中的参数
二、emplace可变模板参数的实际应用
三、逗号表达式展开参数包 一、可变模板参数的概念及功能
1.1Args的概念与使用 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板。 相比 C98/03类模版和函数模版中只能含固定数量的模版参数可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象使用起来需要一定的技巧所以这块还是比较晦涩的。现阶段呢我们掌握一些基础的可变参数模板特性就够我们用了所以这里我们点到为止以后大 家如果有需要再可以深入学习。 // Args是一个模板参数包args是一个函数形参参数包
// 声明一个参数包Args...args这个参数包中可以包含0到任意个模板参数。
template class ...Args
void ShowList(Args... args)
{} 我们可以很清晰的看到Args中有多少个参数。 1.2获取args中的参数 基于上面的代码我们可以感觉到args这个可变模板参数好像和main函数中的命令行参数argv有些许相似那我们可不可以用for循环来取出其中的参数呢当然不可以 c语言中的可变参数是用一个数组进行存储然后在运行时进行解析所以可以在运行时用运行逻辑解析但现在是模板参数模板参数在编译时解析在编译时就要去推该模板是什么类型。 上面的参数args前面有省略号所以它就是一个可变模版参数我们把带省略号的参数称为“参数 包”它里面包含了0到NN0个模版参数。我们无法直接获取参数包args中的每个参数的只能通过展开参数包的方式来获取参数包中的每个参数这是使用可变模版参数的一个主要特点也是最大的难点即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变参数所以我们的用一些奇招来依次获取参数包的值——也就是编译时递归解析。 这时需要写一个递归子函数。 // 递归终止函数
template class T
void ShowList(const T t)
{cout t endl;
}
// 展开函数
template class T, class ...Args
void ShowList(T value, Args... args)
{cout value ;ShowList(args...);
}
int main()
{ShowList(1);ShowList(1, A);ShowList(1, A, std::string(sort));return 0;
} 二、emplace可变模板参数的实际应用 emplace_back就是支持了多参数可变模板的插入对于有移动构造的需要深拷贝的对象来说效率提升不是非常明显。对于浅拷贝类型的对象来说可以提升效率。比如我们之前的Date日期类。
class Date
{
public:Date(int year0,int month0,int day0 ):_year(year),_month(month),_day(day){cout 构造 endl;}Date(const Date d):_year(d._year), _month(d._month), _day(d._day){cout 拷贝构造 endl;}
private:int _year;int _month;int _day;
};
int main()
{listDate lt1;lt1.push_back({ 2024,4,8 });//emplace不支持如下的写法//lt1.emplace_back({ 2024,4,8 });lt1.emplace_back(2024,4,8 );cout endl;Date d1(2024, 4, 9);cout endl;lt1.push_back(d1);lt1.emplace_back(d1);return 0;
} 可以看到如果直接传一个对象进去一般都是进行拷贝构造而直接传参emplace会直接调用构造所以使用emplace时建议直接传参。
直接给插入对象参数的情况下
emplace系列深拷贝的类对象减少一次移动构造浅拷贝的类对象减少一次拷贝构造。 C11中STL的重大变化
1、新容器
2、容器的移动构造和移动赋值
3、新接口 pus/insert/emplace右值版本
三、逗号表达式展开参数包
注一种及其令博主感到懵*的全新的使用方式不禁感叹这还是C吗兄弟你令我感到陌生 这种展开参数包的方式不需要通过递归终止函数是直接在expand函数体中展开的, printarg 不是一个递归终止函数只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式 实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。 expand函数中的逗号表达式(printarg(args), 0)也是按照这个执行顺序先执行printarg(args)再得到逗号表达式的结果0。同时还用到了C11的另外一个特性——初始化列表通过初始化列表来初始化一个变长数组, {(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... )最终会创建一个元素值都为0的数组int arr[sizeof...(Args)]。由于是逗号表达式在创建数组的过程中会先执行逗号表达式前面的部分printarg(args)打印出参数也就是说在构造int数组的过程中就将参数包展开了这个数组的目的纯粹是为了在数组构造的过程展开参数包。