前言
一、可变参数模板
template<class ...Args>
void showList(Args... args)
{
// ...
}
1、关于解包的两种方式
// 方法一:递归取参
void showList()
{
cout << endl;
}
template<class T, class ...Args>
void showList(const T& t, Args... args)
{
cout << t << " ";
showList(args...);
}
void test13()
{
showList();
showList(1);
showList(1, 'x');
showList(1, 1.11, 'y');
}
// 方式二:利用数组自动推导元素个数
template <class T>
void PrintArg(T t)
{
cout << t << " ";
}
template <class ...Args>
void ShowList(Args... args)
{
// 逗号表达式
int arr[] = { 0, (PrintArg(args), 0)...};
cout << endl;
}
void test13()
{
ShowList();
ShowList(1);
ShowList(1, 'x');
ShowList(1, 1.11, 'y');
}
2、emplace系类接口


void test14()
{
list<MySpace::string> l1;
MySpace::string str1("hello");
// 无区别
l1.push_back(str1); // 深拷贝
l1.emplace_back(str1); // 深拷贝
cout << endl << endl;
// 无区别
l1.push_back(move(str1)); // 移动构造
l1.emplace_back(move(str1)); // 移动构造
cout << endl << endl;
// 有区别
l1.push_back("11111"); // 拷贝构造 + 移动构造
l1.emplace_back("11111"); // 直接构造
}
二、lambda
1、初始lambda
struct Goods
{
string _name; // 名字
double _price; // 价格
int _evaluate; // 评价
Goods(const char* str, double price, int evaluate)
:_name(str)
, _price(price)
, _evaluate(evaluate)
{}
};
struct CmpByPriceLess
{
bool operator()(const Goods& x, const Goods& y)
{
return x._price < y._price;
}
};
struct CmpByPriceGreater
{
bool operator()(const Goods& x, const Goods& y)
{
return x._price > y._price;
}
};
void test1()
{
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
// 价格升序
sort(v.begin(), v.end(), CmpByPriceLess());
// 价格降序
sort(v.begin(), v.end(), CmpByPriceGreater());
}
2、lambda的使用
void test1()
{
vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
3 }, { "菠萝", 1.5, 4 } };
// 价格升序
//sort(v.begin(), v.end(), CmpByPriceLess());
// 价格降序
//sort(v.begin(), v.end(), CmpByPriceGreater());
// 价格升序
sort(v.begin(), v.end(), [](const Goods& x, const Goods& y)mutable->bool
{
return x._price < x._price;
});
// 价格降序
sort(v.begin(), v.end(), [](const Goods& x, const Goods& y)mutable->bool
{
return x._price > x._price;
});
}
void test2()
{
int a = 3;
int b = 5;
// 值捕捉
auto add = [a, b]()mutable->int
{
a++;
return a + b;
};
// 全部值捕捉(若无参数,括号可省略;一般情况下,返回值也可以省略)
// 如果不期望修改值传递进来的值,mutable也可以省略;
auto sub = [=] { return a - b; };
cout << add() << endl;
cout << sub() << endl;
cout << a << endl;
}
void test3()
{
int x = 3;
int y = 4;
// 若添加了mutable则圆括号不可省略
auto f1 = [&x, y]()mutable {x = 1; y = 2; };
f1();
cout << x << " " << y << endl;
// 将上文所有变量以引用的方式进行捕捉
auto f2 = [&] {x = 10; y = 20; };
cout << x << " " << y << endl;
}
class A
{
public:
void func()
{
// 捕获当前类的this指针
auto f1 = [this] {cout << _a << endl; };
}
private:
int _a = 0;
};
3、lambda的底层原理
// 是否正确?
void test3()
{
auto f1 = [](int x, int y) {return x + y; };
//auto f2 = [](int x, int y) {return x + y; };
auto f2 = [](int x, int y) {return x - y; };
f1 = f2;
}
struct Fun
{
int operator()(int x, int y)
{
return x + y;
}
};
void test4()
{
auto f1 = [](int x, int y) { return x + y; };
Fun f2;
// 调用lambda函数
f1(2, 5);
// 调用仿函数
f2(2, 5);
}

三、包装器
1、初始function
struct ADD
{
int operator()(int x, int y)
{
return x + y;
}
};
int add(int x, int y)
{
return x + y;
}
void test5()
{
// 包装器封装仿函数
function<int(int, int)> f1 = ADD();
// 包装器封装函数指针
int(*pf)(int, int) = add;
function<int(int, int)> f1 = pf;
// 包装器封装lambda函数
function<int(int, int)> f1 = [](int x, int y) { return x + y; };
}
class A
{
public:
// 静态成员函数
static int func1(int x, int y)
{
return x + y;
}
// 普通成员函数
int func2(int x, int y)
{
return x + y;
}
private:
};
void test6()
{
// 封装静态成员函数(类名前可加&也可不加)
//function<int(int, int)> f1 = A::func1;
function<int(int, int)> f1 = &A::func1;
// 封装普通成员函数(类型前必须加&,语法规定,且参数列表中声明类名)
function<int(A, int, int)> f2 = &A::func2;
}
2、包装器的使用场景
struct functor
{
int operator()(int x, int y)
{
return x - y;
}
};
int mul(int x, int y)
{
return x * y;
}
void test7()
{
vector<function<int(int x, int y)>> vfs;
// lambda函数
vfs.push_back([](int x, int y)-> int {return x + y; });
// 仿函数
functor ft;
vfs.push_back(ft);
// 函数指针
int(*ptr)(int, int) = mul;
vfs.push_back(ptr);
}
3、bind
// 调整参数顺序
void Func1(int x, int y)
{
cout << x << " " << y << endl;
}
void test8()
{
// 调整参数顺序
Func1(10, 20);
// placeholder为命名空间,_1,_2....._n都为调整的参数顺序
auto f1 = bind(Func1, placeholders::_2, placeholders::_1);
// 写法二
function<void(int, int)> f2 = bind(Func1, placeholders::_2, placeholders::_1);
f1(10, 20);
}
// 调整参数个数
class Cal
{
public:
Cal(double rate = 2.5)
:_rate(rate)
{}
double cal(int x, int y)
{
return (x + y) * _rate;
}
private:
double _rate;
};
void test9()
{
int x = 3;
int y = 6;
Cal c1;
cout << c1.cal(x, y) << endl;
// 调整参数个数
auto func2 = bind(&Cal::cal, c1, placeholders::_1, placeholders::_2);
cout << func2(x, y) << endl;
}
四、线程库
1、线程库相关接口




2、关于线程库中的一些细节问题
// vs下查看
typedef struct
{
/* thread identifier for Win32 */
void *_Hnd; /* Win32 HANDLE */
unsigned int _Id;
} _Thrd_imp_t;
void Func1()
{
cout << "thread 1" << endl;
}
struct Func2
{
void operator()()
{
cout << "thread 2" << endl;
}
};
int main()
{
// 函数指针
thread t1(Func1);
// 传仿函数对象
Func2 f2;
thread t2(f2);
// 传lambda函数
thread t3([] { cout << "thread 3" << endl; });
t1.join();
t2.join();
t3.join();
return 0;
}
3、线程相关接口

4、线程安全相关问题
static int sum = 0;
void transaction(int num)
{
for (int i = 0; i < num; i++)
{
sum++;
}
}
int main()
{
// 创建线程
//template <class Fn, class... Args>
//explicit thread(Fn && fn, Args&&... args);
// 参数一fn通常是一个函数指针,表示该线程调用的函数
// 参数二是可变模板参数,会自动解析,并传给我们参数函数指针所指向的函数
thread t1(transaction, 100000);
thread t2(transaction, 200000);
// 线程等待(必须进行线程等待,除非子线程执行函数中进行了detach)
t1.join();
t2.join();
cout << sum << endl;
return 0;
}

5、锁的分类


static int sum = 0;
mutex mx; // 创建锁变量
void transaction(int num)
{
// 上锁
mx.lock();
for (int i = 0; i < num; i++)
{
sum++;
}
mx.unlock(); // 解锁
}
int main()
{
thread t1(transaction, 100000);
thread t2(transaction, 200000);
t1.join();
t2.join();
cout << sum << endl;
return 0;
}
6、lockguard
#pragma once
#include <mutex>
template<class Lock>
class Lockguard
{
public:
Lockguard(std::Lock& mt)
:_mt(mt)
{
_mt.lock();
}
~Lockguard()
{
_mt.unlock();
}
private:
std::Lock& _mt;
};


static int sum = 0;
mutex mx; // 创建锁变量
void transaction(int num)
{
// 出作用域自动销毁
lock_guard<mutex> lg(mx);
for (int i = 0; i < num; i++)
{
sum++;
}
}
int main()
{
thread t1(transaction, 100000);
thread t2(transaction, 200000);
t1.join();
t2.join();
cout << sum << endl;
return 0;
}
7、条件变量
