
目录
1 可变参数模板
C++11 支持可变参数模板,使用...代表参数包。分为模板参数包、函数参数包。
template<class ...Args>
void Print(Args... args)
{
cout << sizeof...(args) << endl; // sizeof... 获取参数包中参数个数
}
Args...模板参数包;args...函数参数包。sizeof...(args):编译期拿到参数包里面参数总个数。
参数包不能用 for 循环遍历,只能通过编译期递归展开。
递归展开示例:
#include<iostream>
#include<string>
using namespace std;
//递归终止,参数包为空
void ShowList()
{
cout << endl;
}
template<class T, class ...Args>
void ShowList(T x, Args... args)
{
cout << x << " ";
ShowList(args...); // 剥掉第一个参数,剩下继续递归
}
template<class ...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::forward<Args>(args)...,把参数转发给结点的构造函数。
示例 list 模拟结点:
template<class T>
struct ListNode
{
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;
//支持可变参数直接构造data
template<class... Args>
ListNode(Args&&... args)
:_data(std::forward<Args>(args)...)
{}
};
调用示例:
list<pair<string,int>> lt;
lt.emplace_back("苹果",1); //直接传给pair构造,不用手动构造pair临时对象
3 C++11 类新语法:default、delete
C++98 类 6 个默认成员:
- 构造函数
- 拷贝构造
- 拷贝赋值重载
- 析构函数
- 取地址
operator& - const 取地址
operator&
C++11 新增两个默认成员函数:移动构造、移动赋值。
规则:
- 没有自己写析构、拷贝构造、拷贝赋值,编译器才会自动生成默认移动构造 / 移动赋值。
=default:强制让编译器生成默认版本函数。=delete:删除函数,禁止调用该函数(C++98 时代把函数放 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; //删除拷贝赋值,禁止使用
};
另外 C++11 支持类内成员变量直接初始化缺省值,给初始化列表提供默认值。
4 lambda 表达式
lambda 本质:编译器自动生成匿名仿函数类。 完整语法:
[捕获列表](参数列表) -> 返回类型 {函数体};
[]捕获列表,不可省略;()参数列表,无参数可以省略;->返回类型追踪返回类型,可以省略,编译器自动推导;{}函数体,不可省略。
捕获规则
表格
| 写法 | 含义 |
|---|---|
[x] | 值捕获,拷贝一份,默认 const,不能修改 |
[&x] | 引用捕获,直接使用外部变量本体,可以修改 |
[=] | 隐式值捕获:用到的变量全部值捕获 |
[&] | 隐式引用捕获:用到的变量全部引用捕获 |
[=, &a] | 其它值捕获,a 引用捕获 |
[&, a] | 其它引用捕获,a 值捕获 |
- mutable:加在参数括号后面,取消值捕获变量的 const 属性,可以修改拷贝副本,不会影响外部实参。
- 全局变量、静态局部变量不需要捕获,可以直接使用;lambda 写在全局域,捕获列表必须为空。
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
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()
{
vector<Goods> 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::function<Ret(Args...)>:统一包装各类可调用对象:普通函数、函数指针、仿函数、lambda 表达式、bind 返回对象。 解决不同可调用对象类型不一样,无法统一保存的问题。 如果function对象没有包装目标,调用会抛出bad_function_call异常。
#include<functional>
#include<iostream>
using namespace std;
int f(int a,int b)
{
return a+b;
}
struct Functor
{
int operator()(int a,int b)
{
return a+b;
}
};
int main()
{
function<int(int,int)> f1 = f;
function<int(int,int)> f2 = Functor();
function<int(int,int)> f3 = [](int a,int b){return a+b;};
cout << f1(1,2) << endl;
cout << f2(1,2) << endl;
cout << f3(1,2) << endl;
return 0;
}
6 std::bind 适配器
头文件<functional>;bind 是函数适配器,包装可调用对象,可以:
- 绑定固定参数;
- 调整参数顺序; 占位符
_1 _2 _3定义在std::placeholders命名空间。
#include<functional>
#include<iostream>
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删除函数,禁止调用。C++11 新增移动构造、移动赋值两个默认成员。- lambda 是编译器生成匿名仿函数,掌握捕获列表、mutable;适合算法 sort 等场景写临时逻辑。
std::function统一包装不同类型可调用对象;std::bind做参数绑定、顺序调整适配器。
后续 C++11 其余特性:智能指针、unordered 哈希容器、范围 for、override/final、string_view 等属于其他章节。

转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/wuqingyigexiaoba/article/details/166902229




