)
目录1 可变参数模板2 emplace 系列接口3 C11 类新语法default、delete4 lambda 表达式捕获规则5 std::function 包装器6 std::bind 适配器小结1 可变参数模板C11 支持可变参数模板使用...代表参数包。分为模板参数包、函数参数包。templateclass ...Args void Print(Args... args) { cout sizeof...(args) endl; // sizeof... 获取参数包中参数个数 }Args...模板参数包args...函数参数包。sizeof...(args)编译期拿到参数包里面参数总个数。参数包不能用 for 循环遍历只能通过编译期递归展开。递归展开示例#includeiostream #includestring using namespace std; //递归终止参数包为空 void ShowList() { cout endl; } templateclass T, class ...Args void ShowList(T x, Args... args) { cout x ; ShowList(args...); // 剥掉第一个参数剩下继续递归 } templateclass ...Args void Print(Args... args) { ShowList(args...); } int main() { Print(); Print(1); Print(1, string(hello)); Print(1.1, 2, abc); return 0; }原理编译阶段实例化出多份重载函数不是运行时解析参数。2 emplace 系列接口容器新增emplace_back / emplace接收可变参数包。push_back需要已经构造完成对象再拷贝 / 移动进入容器emplace_back(Args... args)直接在容器结点内存上构造对象不需要生成临时对象。底层可变参数包 完美转发std::forwardArgs(args)...把参数转发给结点的构造函数。示例 list 模拟结点templateclass T struct ListNode { T _data; ListNodeT* _prev; ListNodeT* _next; //支持可变参数直接构造data templateclass... Args ListNode(Args... args) :_data(std::forwardArgs(args)...) {} };调用示例listpairstring,int lt; lt.emplace_back(苹果,1); //直接传给pair构造不用手动构造pair临时对象3 C11 类新语法default、deleteC98 类 6 个默认成员构造函数拷贝构造拷贝赋值重载析构函数取地址operatorconst 取地址operatorC11 新增两个默认成员函数移动构造、移动赋值。规则没有自己写析构、拷贝构造、拷贝赋值编译器才会自动生成默认移动构造 / 移动赋值。default强制让编译器生成默认版本函数。delete删除函数禁止调用该函数C98 时代把函数放 private 实现同样效果。示例class Person { public: Person(const char* name , int age 0){} Person(const Person p){} Person(Person p) default; //强制生成默认移动构造 Person operator(Person p) default; Person operator(const Person p) delete; //删除拷贝赋值禁止使用 };另外 C11 支持类内成员变量直接初始化缺省值给初始化列表提供默认值。4 lambda 表达式lambda 本质编译器自动生成匿名仿函数类。 完整语法[捕获列表](参数列表) - 返回类型 {函数体};[]捕获列表不可省略()参数列表无参数可以省略-返回类型追踪返回类型可以省略编译器自动推导{}函数体不可省略。捕获规则表格写法含义[x]值捕获拷贝一份默认 const不能修改[x]引用捕获直接使用外部变量本体可以修改[]隐式值捕获用到的变量全部值捕获[]隐式引用捕获用到的变量全部引用捕获[, a]其它值捕获a 引用捕获[, a]其它引用捕获a 值捕获mutable加在参数括号后面取消值捕获变量的 const 属性可以修改拷贝副本不会影响外部实参。全局变量、静态局部变量不需要捕获可以直接使用lambda 写在全局域捕获列表必须为空。#includeiostream #includevector #includealgorithm #includestring using namespace std; struct Goods { string _name; double _price; int _evaluate; Goods(const char* str, double price, int evaluate) :_name(str),_price(price),_evaluate(evaluate) {} }; int main() { vectorGoods v { {苹果, 2.1, 5}, {香蕉,3,4},{橙子,2.2,3},{菠萝,1.5,4} }; sort(v.begin(),v.end(),[](const Goods g1,const Goods g2){ return g1._price g2._price; }); return 0; }lambda 底层原理编译器生成一个仿函数类捕获的变量变成类的成员调用 lambda 等价调用仿函数operator()。5 std::function 包装器头文件functional。std::functionRet(Args...)统一包装各类可调用对象普通函数、函数指针、仿函数、lambda 表达式、bind 返回对象。 解决不同可调用对象类型不一样无法统一保存的问题。 如果function对象没有包装目标调用会抛出bad_function_call异常。#includefunctional #includeiostream using namespace std; int f(int a,int b) { return ab; } struct Functor { int operator()(int a,int b) { return ab; } }; int main() { functionint(int,int) f1 f; functionint(int,int) f2 Functor(); functionint(int,int) f3 [](int a,int b){return ab;}; cout f1(1,2) endl; cout f2(1,2) endl; cout f3(1,2) endl; return 0; }6 std::bind 适配器头文件functionalbind 是函数适配器包装可调用对象可以绑定固定参数调整参数顺序 占位符_1 _2 _3定义在std::placeholders命名空间。#includefunctional #includeiostream using namespace std; using placeholders::_1; using placeholders::_2; int Sub(int a,int b) { return (a-b)*10; } int main() { auto sub1 bind(Sub,_1,_2); cout sub1(10,5) endl; auto sub2 bind(Sub,_2,_1); //交换参数顺序 cout sub2(10,5) endl; auto sub3 bind(Sub,100,_1); //第一个参数固定100 cout sub3(5) endl; return 0; }小结可变参数模板依靠编译递归展开参数包sizeof...(args)拿到参数数量emplace依靠可变参数 完美转发直接在容器内存构造对象。default强制生成编译器默认函数delete删除函数禁止调用。C11 新增移动构造、移动赋值两个默认成员。lambda 是编译器生成匿名仿函数掌握捕获列表、mutable适合算法 sort 等场景写临时逻辑。std::function统一包装不同类型可调用对象std::bind做参数绑定、顺序调整适配器。后续 C11 其余特性智能指针、unordered 哈希容器、范围 for、override/final、string_view 等属于其他章节。