尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

C++ 11:可变参数模板

发布时间:2026/9/30 2:28:12

资讯中心
01
ARTICLE

C++ 11:可变参数模板

C++ 11:可变参数模板
目录一.基本语法及原理二.包扩展三.emplace系列接口一.基本语法及原理C11 支持可变参数模板也就是说支持可变数量参数的函数模板和类模板可变数目的参数被称为参数包存在两种参数包模板参数包表示零或多个模板参数函数参数包表示零或多个函数参数。template class ...Args void Func(Args... args) {} template class ...Args void Func(Args... args) {} template class ...Args void Func(Args... args) {}我们用省略号来指出一个模板参数或函数参数表示一个包在模板参数列表中class... 或 typename... 指出接下来的参数表示零或多个类型列表在函数参数列表中类型名后面跟... 指出接下来表示零或多个形参对象列表函数参数包可以用左值引用或右值引用表示跟前面普通模板一样每个参数实例化时遵循引用折叠规则。可变参数模板的原理跟模板类似本质还是去实例化对应类型和个数的多个函数。这里我们可以使用 sizeof... 运算符去计算参数包中参数的个数。可变模板参数模板参数包C11 引入使用...声明可以接收任意数量、任意类型的模板参数一组打包在一起的类型集合称为参数包。templateclass ...Args // Args 就是【模板参数包】 void Func(Args... args) // args 是【函数参数包】 { }class ...Args/typename ...Args模板参数包存放一堆类型Args... args函数参数包存放一堆函数实参 符号...叫做省略号用来标识 “包”。区分两个概念模板参数包...Args→ 一堆类型函数参数包Args... args→ 一堆变量核心语法规则sizeof...(包名)用来获取参数包里参数的数量templateclass ...Args void Test(Args... args) { cout sizeof...(Args) endl; // 类型个数 cout sizeof...(args) endl; // 参数个数二者相等 }参数包不能直接遍历C11依靠递归展开拆包 C17新增折叠表达式简化展开编译器原理 可变模板不是一个能接收无限参数的单个函数编译器根据你传入参数的数量与类型实例化出多个不同签名的函数。Func(1,2,abc); Func(10); // 生成两份不同实例函数项目sizeofsizeof...作用求内存占用字节数求参数包内元素数量操作对象普通类型、变量、表达式模板参数包 / 函数参数包能不能用于可变参数以外✅ 随处可用❌ 只能配合参数包括号内能不能加...不能参数包名后面不能再加...返回值含义字节大小 (size_t)参数个数 (size_t)二.包扩展1. 定义包扩展使用...把参数包里所有元素展开逐个铺开。只有存在参数包模板参数包Args.../ 函数参数包args...时才能进行包扩展。编译器会把模式复制多份包中每一个元素对应一份。C还⽀持更复杂的包扩展直接将参数包依次展开依次作为实参给⼀个函数去处理。下面这种写法不对编译会报错为什么呢首先参数包是在编译时进行推导的但这种写法是在运行时相当于编译器走到这里会先编译出合适的类型再进行运行但下面是运行时的过程只有编译完才会运行编译都没进行这就会报错其次这是可变模板参数传过来的数据类型都不一样怎么能用同意容器来存放不同的数据类型// 递归出口 void Print(){} templateclass T, class ...Args void Print(T first, Args... args) { cout first ; Print(args...); // args... 包扩展递归调用 }调用Print(1,2,3)Print(args...)→Print(2,3)下一轮 →Print(3)下一轮 →Print()包扩展只有这个作用吗下面我们讲解重要作用三.emplace系列接口#includelist // emplace_back总体而言是更高效推荐以后使用emplace系列替代insert和push系列 int main() { listbit::string lt; // 传左值跟push_back一样走拷贝构造 bit::string s1(11111111111); lt.emplace_back(s1); cout ***************************** endl; // 右值跟push_back一样走移动构造 lt.emplace_back(move(s1)); cout ***************************** endl; // 直接把构造string参数包往下传直接用string参数包构造string // 这里达到的效果是push_back做不到的 lt.emplace_back(1111111111); cout ***************************** endl; listpairbit::string, int lt1; // 跟push_back一样 // 构造pair 拷贝/移动构造pair到list的节点中data上 pairbit::string, int kv(苹果, 1); lt1.emplace_back(kv); cout ***************************** endl; // 跟push_back一样 lt1.emplace_back(move(kv)); cout ***************************** endl; //////////////////////////////////////////////////////////////////// // 直接把构造pair参数包往下传直接用pair参数包构造pair // 这里达到的效果是push_back做不到的 lt1.emplace_back(苹果1, 1); cout ***************************** endl; return 0; }一、分 3 种调用场景对比重点场景 1传入已经存在的对象左值bit::string s1(11111); lt.emplace_back(s1);等价于push_back(s1)s1左值T 推导为bit::string原地调用拷贝构造函数创建容器内对象。场景 2传入右值std::movelt.emplace_back(move(s1));等价于push_back(std::move(s1))move(s1)是右值T 推导为bit::string原地调用移动构造函数。上面两种写法emplace_back和push_back性能表现基本一致。场景 3【emplace 独有的优势】直接传入构造参数包 ⭐// push_back 无法直接这样写 lt.emplace_back(1111111111); lt1.emplace_back(苹果1, 1);发生了什么字符串字面量11111、苹果1,1作为参数包完整传入emplace_back通过std::forwardArgs(args)...包扩展 完美转发直接在 list 节点的内存上调用对应构造函数✅不需要临时对象和 push_back 对比lt.push_back(1111111111); // push_back内部行为 // 1. 先用字面量构造一个临时 bit::string临时对象 // 2. 将临时对象移动构造进容器节点 // 存在一次多余临时对象构造析构对于pairbit::string,intlt1.emplace_back(苹果1, 1); // 直接原地调用 pair 的构造 pair(const char*, int)如果使用 push_backlt1.push_back(make_pair(苹果1,1)); // 需要先构造临时pair再移动进容器多一次开销二、关键总结当传入现成对象左值 / 右值emplace_back≈push_back没有明显优势。当直接传入构造所需参数列表emplace_back优势巨大零临时对象原地构造这是 push_back 无法实现的写法。底层技术栈串联你全部学过的内容 万能引用 → 引用折叠 → 可变参数模板参数包→包扩展→ std::forward 完美转发 → emplace 原地构造。三、面试标准问题Qemplace_back 和 push_back 的区别push_back接收已经构造完成的元素对象emplace_back接收构造对象所需的参数包原地直接构造emplace_back 可以避免产生临时对象减少拷贝 / 移动开销emplace_back 依靠可变参数模板、万能参数包、完美转发实现。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。