C++11常用特性学习——多线程优化初步(原子类型/lambda语句)
2015-11-24 20:35
387 查看
C11多线程原子类型
C98/03主要使用互斥等操作来保证线程中数据操作的安全性,这样,数据的修改必须加上thread_mutex等原子锁等来保证数据修改的准确性。有时为了高性能或底层工作,要求线程间的通信没有开销巨大的互斥锁.原子操作可以达到这个目的,这可以随意地为一个操作指定最小的内存可见度。通过<cstdatomic>中封装和定义了通用的原子类型,原子类型在通用类型前加atomic_即对应原子类型。如atomic_bool——bool,atomic_int——int,atomic_uint——unsigned int,atomic_llong——long long;
更普遍地,可以使用atomic类模板,通过该类模板,可以任意定义出需要的原子类型:
std::atomic<T> t。
对于线程而言,原子类型通常属于资源型”的数据,这意味着多个线程通常只能访问单个原子类型的拷贝。因此在C++中,原子类型只能从其模板参数类型中进行构造,标准不允许原子类型进行拷贝构造、移动构造,以及使用operator=等,以防止发生意外。比如:
atomic<float> af {1.2f};
atomic<float> af1 {af};//无法编译通过
事实土,atomic模板类的拷贝构造函数、移动构造函数、operator=等总是默认被删除的。《深入理解C++11新特性解析与应用》中第7章有有如何删除一些默认函数的方法。
但是可以:
atomic<int> a;
a = 1;//,等同于a.store(1)
atomic<int> b;
int c = b;//,等同于c=b.load()
C11多线程内存模型
主要涉及到内存模型、memory_order等知识点。相关函数:memory_order_relaxed
memory_order_acquire
memory_oreder_release
memory_order_acq_rel
memory_order_consume
memory_order_seq_cst
关于些 C11在并发编程等方面的新特性和关键知识点:可以参考C++11 并发指南系列 ;
C11的lambda函数
Lambda表达式用于定义并创建匿名的函数对象。java8等已经广泛使用lambda函数形式。C++11页引入了这种模式。Lambda表达式具体形式如下:[函数对象参数] (操作符重载函数参数) mutable或exception声明 ->返回值类型 {函数体}
[capture](parameters)->return-type{body}
如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:
[capture](parameters){body}。
几个Lambda函数的例子:
[](int x, int y) { return x + y; } // 隐式返回类型 [](int& x) { ++x; } // 没有return语句 -> lambda 函数的返回类型是'void' []() { ++global_x; } // 没有参数,仅访问某个全局变量 []{ ++global_x; } // 与上一个相同,省略了() [](int x, int y) -> int { int z = x + y; return z; } //显示指定返回类型:
[capture]捕捉列表。捕捉列表总是出现在lambda函数的开始处。事实上[]是lambda引出符.。编译器根据该引出符判断接下来的代码是否是lambda}函数。捕捉列表能够捕捉上下文中的变量供lambda函数使用。Lambda函数可以引用在它之外声明的变量. 这些变量的集合叫做一个闭包. 闭包被定义在Lambda表达式声明中的方括号[]内. 这个机制允许这些变量被按值或按引用捕获.下面这些例子就是:
[] //未定义变量.试图在Lambda内使用任何外部变量都是错误的. [x, &y] //x 按值捕获, y 按引用捕获. [&] //用到的任何外部变量都隐式按引用捕获,(相当于编译器自动为我们按引用传递了所有局部变量) [=] //用到的任何外部变量都隐式按值捕获,(相当于编译器自动为我们按值传递了所有局部变量) [&, x,y] //x显式地按值捕获. 其它变量按引用捕获,(除X和y按值进行传递外,其他参数都按引用进行传递) [=, &z] //z按引用捕获. 其它变量按值捕获,(除z按引用进行传递外,其他参数都按值进行传递。)
和普通函数一样,中间值不会保存到下次调用。什么也不返回的Lambda函数可以省略返回类型, 而不需要使用 -> void 形式。
如:
std::vector<int> some_list; int total = 0; for (int i=0;i<5;++i) some_list.push_back(i); std::for_each(begin(some_list), end(some_list), [&total](int x) { total += x; });
一般可以用auto表示lambda函数
int main() { int a =3, b=4; auto total = [] (int x ,int y)->int{ return x + y}; return total(a,b); }
上面函数使用传值,可以使用传参数来改写上面函数:
int main() { int a =3, b=4; auto total = [a,&b] ()->int{ return a + b}; return total(); }
lambda还支持仿函数的形式;
重载类的operator()函数就能得到一个仿函数的类;
相关文章推荐
- 在 Qt4 中使用 C++11
- centos安装devtoolset-3支持gcc 4.9.2
- 使用eclipse编译含有C++11特性的代码
- 怎样在Linux环境编译支持C11
- eclipse支持c++11
- C++11可变参数函数与for循环
- vs2013 编译c++是发现惊天bug
- 简单性能测试函数模板
- 关于C++现状的一些思考
- 用C++11优化矩阵运算的空间和时间效率
- 浅析构造函数之默认构造函数
- c++中返回数组的函数
- C++函数重载的几个问题
- C++11 note-2 字符串 容器 迭代器
- C++11 现代C++风格的新元素
- c++11 lambda表达式浅谈
- C++11之“move”语意
- C++11之Lambda表达式
- C++11特性乱弹
- 掀起C++ 11的神秘面纱(1)