现代C++实战(4)
作者:互联网
函数对象
c++98中的函数对象:重载()运算符
struct Add {
Add(int n): n_(n){}
int operator()(x) const {
return x + n_;
}
private:
int n_;
}
Lambda表达式
auto add_2 = [](int x) {return x + 2;};
变量捕获
- 本地变量按值捕获
- & 按引用捕获
泛型Lambda
// 普通泛型函数
template<typename T1, typename T2>
auto sum(T1 x, T2 y) {
return x + y;
}
// 等价的lambda表达式
auto sum = [](auto x, auto y) {
return x + y;
};
bind和functional
plus<>()接受两个参数,bind将2绑定到第二个参数,如果不绑定,则用_1,_2用作占位符
transform(v.begin(), v.end(), v.begin(), bind(plus<>(), _1, 2))
function模板是一个包装
function<int(int, int)> a; // 一个返回值为int,接受两个int参数的function对象
上述function对象,可以接受函数签名为int(int,int)的可调用的对象(lambda表达式,函数指针,函数对象,函数名)
函数式编程
要说清楚什么是函数式编程还是很困难的,不过大概的意思就是,把函数当参数传给其他的函数去执行。
可变模板和tuple
模板参数的个数是不定的,下面是个一般用法
template<typename T, typename ...Args>
inline unique_ptr<T>
make_unique (Args&&... args)
{
return unique_ptr<T>(new T(forward<Args>(args)...));
}
这里用forward是为了保持原有的左右值特性(因为右值引用经过一次传参后会变成左值)
递归用法
求n个数的和,变参
template<typename T>
constexpr auto sum(T x) {
return x;
}
template<typename T1, typename T2, typename... Args>
constexpr auto sum(T1, x, T2, y, Args... args) {
return sum(x + y, args);
}
tuple
thread和future
基于thread的多线程
#include <thread>
#include <iostream>
using namespace std;
void func1() {
this_thread::sleep_for(100ms); // 全局函数
cout << "func1!" << endl;
}
void func2() {
cout << "func2!" << endl;
}
int main() {
thread t1{ func1 };
thread t2{ func2 };
t1.join(); // 必须join或者detach
t2.join();
}
mutex 互斥量
- mutex
- recursive_mutex
- timed_mutex
- recursive_timed_mutex
- shared_mutex
- shared_timed_mutex
lock_gard,mutex的RAII包装类
锁
- unique_lock
- scope_lock
future
#include <thread>
#include <iostream>
#include <future>
using namespace std;
int func1() {
this_thread::sleep_for(100ms);
cout << "func1!" << endl;
return 1;
}
void func2() {
cout << "func2!" << endl;
}
int main() {
auto a = async(launch::async, func1);
this_thread::sleep_for(1s);
cout << "I am waiting now\n";
cout << "Answer: " << a.get() << endl;
}
- async指定执行的方式,launch::async表示异步
- 返回一个future对象,用该对象获取结果
内存模型和atomic
双重检查
看一个单例模式
class Singleton{
public:
static Singleton* instance();
private:
static Singleton* inst_ptr_;
}
如何保证多线程下,inst_ptr_不会被初始化两次?
// 一阶段
// 每次调用都需要加锁
Singleton* Singleton::instance() {
{
lock_guard lock;
if (inst_ptr == nullptr) {
inst_ptr_ = new Singleton();
}
return inst_ptr_;
}
// 二阶段
// 初始化以后就不用枷锁了
Singleton* Singleton::instance() {
if (inst_ptr_ == nullptr) {
lock_guard lock;
if (inst_ptr == nullptr) {
inst_ptr_ = new Singleton();
}
}
return inst_ptr_;
}
volatile
防止编译器“优化”掉对内存的读写
atomic
c++11 对原子对象进行了封装
原子操作:读,写,读-修改-写(读到内存,修改,写回内存)
标签:实战,Singleton,return,int,C++,现代,inst,mutex,ptr 来源: https://www.cnblogs.com/destinyzk/p/16573716.html