struct Add { Add(int n): n_(n){} int operator()(x) const { return x + n_; } private: int n_; }
auto add_2 = [](int x) {return x + 2;};
变量捕获
// 普通泛型函数 template<typename T1, typename T2> auto sum(T1 x, T2 y) { return x + y; } // 等价的lambda表达式 auto sum = [](auto x, auto y) { return x + y; };
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表达式,函数指针,函数对象,函数名)
要说清楚什么是函数式编程还是很困难的,不过大概的意思就是,把函数当参数传给其他的函数去执行。
模板参数的个数是不定的,下面是个一般用法
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); }
#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(); }
lock_gard,mutex的RAII包装类
#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; }
看一个单例模式
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_; }
防止编译器“优化”掉对内存的读写
c++11 对原子对象进行了封装
原子操作:读,写,读-修改-写(读到内存,修改,写回内存)