C/C++教程

现代C++实战(4)

本文主要是介绍现代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 对原子对象进行了封装

原子操作:读,写,读-修改-写(读到内存,修改,写回内存)

这篇关于现代C++实战(4)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!